daily update
[deliverable/binutils-gdb.git] / bfd / mach-o.c
CommitLineData
3af9a47b 1/* Mach-O support for BFD.
4f608e79 2 Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
4a97a0e5 3 2009, 2010, 2011
3af9a47b
NC
4 Free Software Foundation, Inc.
5
6 This file is part of BFD, the Binary File Descriptor library.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
cd123cb7 10 the Free Software Foundation; either version 3 of the License, or
3af9a47b
NC
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a95a4550 19 along with this program; if not, write to the Free Software
cd123cb7
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
3af9a47b 22
3db64b00 23#include "sysdep.h"
3af9a47b
NC
24#include "mach-o.h"
25#include "bfd.h"
3af9a47b
NC
26#include "libbfd.h"
27#include "libiberty.h"
15e1c58a 28#include "aout/stab_gnu.h"
3af9a47b
NC
29#include <ctype.h>
30
154a1ee5
TG
31#define bfd_mach_o_object_p bfd_mach_o_gen_object_p
32#define bfd_mach_o_core_p bfd_mach_o_gen_core_p
42fa0891 33#define bfd_mach_o_mkobject bfd_mach_o_gen_mkobject
116c20d2 34
92bc0e80
TG
35#define FILE_ALIGN(off, algn) \
36 (((off) + ((file_ptr) 1 << (algn)) - 1) & ((file_ptr) -1 << (algn)))
37
ab273af8 38static int bfd_mach_o_read_symtab_symbols (bfd *);
046b007d 39
c2f09c75 40unsigned int
1e8a024a
TG
41bfd_mach_o_version (bfd *abfd)
42{
43 bfd_mach_o_data_struct *mdata = NULL;
44
45 BFD_ASSERT (bfd_mach_o_valid (abfd));
046b007d 46 mdata = bfd_mach_o_get_data (abfd);
1e8a024a
TG
47
48 return mdata->header.version;
49}
50
b34976b6 51bfd_boolean
116c20d2 52bfd_mach_o_valid (bfd *abfd)
3af9a47b
NC
53{
54 if (abfd == NULL || abfd->xvec == NULL)
154a1ee5 55 return FALSE;
3af9a47b 56
154a1ee5
TG
57 if (abfd->xvec->flavour != bfd_target_mach_o_flavour)
58 return FALSE;
3af9a47b 59
046b007d 60 if (bfd_mach_o_get_data (abfd) == NULL)
154a1ee5
TG
61 return FALSE;
62 return TRUE;
63}
64
c2f09c75
TG
65static INLINE bfd_boolean
66mach_o_wide_p (bfd_mach_o_header *header)
67{
68 switch (header->version)
69 {
70 case 1:
71 return FALSE;
72 case 2:
73 return TRUE;
74 default:
75 BFD_FAIL ();
76 return FALSE;
77 }
78}
79
80static INLINE bfd_boolean
81bfd_mach_o_wide_p (bfd *abfd)
82{
046b007d 83 return mach_o_wide_p (&bfd_mach_o_get_data (abfd)->header);
c2f09c75
TG
84}
85
154a1ee5
TG
86/* Tables to translate well known Mach-O segment/section names to bfd
87 names. Use of canonical names (such as .text or .debug_frame) is required
88 by gdb. */
89
90struct mach_o_section_name_xlat
91{
92 const char *bfd_name;
93 const char *mach_o_name;
8462aec7 94 flagword flags;
154a1ee5
TG
95};
96
97static const struct mach_o_section_name_xlat dwarf_section_names_xlat[] =
98 {
8462aec7
TG
99 { ".debug_frame", "__debug_frame", SEC_DEBUGGING },
100 { ".debug_info", "__debug_info", SEC_DEBUGGING },
101 { ".debug_abbrev", "__debug_abbrev", SEC_DEBUGGING },
102 { ".debug_aranges", "__debug_aranges", SEC_DEBUGGING },
103 { ".debug_macinfo", "__debug_macinfo", SEC_DEBUGGING },
104 { ".debug_line", "__debug_line", SEC_DEBUGGING },
105 { ".debug_loc", "__debug_loc", SEC_DEBUGGING },
106 { ".debug_pubnames", "__debug_pubnames", SEC_DEBUGGING },
107 { ".debug_pubtypes", "__debug_pubtypes", SEC_DEBUGGING },
108 { ".debug_str", "__debug_str", SEC_DEBUGGING },
109 { ".debug_ranges", "__debug_ranges", SEC_DEBUGGING },
110 { NULL, NULL, 0}
154a1ee5
TG
111 };
112
113static const struct mach_o_section_name_xlat text_section_names_xlat[] =
114 {
8462aec7
TG
115 { ".text", "__text", SEC_CODE | SEC_LOAD },
116 { ".const", "__const", SEC_READONLY | SEC_DATA | SEC_LOAD },
117 { ".cstring", "__cstring", SEC_READONLY | SEC_DATA | SEC_LOAD },
118 { ".eh_frame", "__eh_frame", SEC_READONLY | SEC_LOAD },
119 { NULL, NULL, 0}
154a1ee5
TG
120 };
121
122static const struct mach_o_section_name_xlat data_section_names_xlat[] =
123 {
8462aec7
TG
124 { ".data", "__data", SEC_DATA | SEC_LOAD },
125 { ".const_data", "__const", SEC_DATA | SEC_LOAD },
126 { ".dyld", "__dyld", SEC_DATA | SEC_LOAD },
127 { ".lazy_symbol_ptr", "__la_symbol_ptr", SEC_DATA | SEC_LOAD },
128 { ".non_lazy_symbol_ptr", "__nl_symbol_ptr", SEC_DATA | SEC_LOAD },
129 { ".bss", "__bss", SEC_NO_FLAGS },
130 { NULL, NULL, 0}
154a1ee5
TG
131 };
132
133struct mach_o_segment_name_xlat
134{
135 const char *segname;
136 const struct mach_o_section_name_xlat *sections;
137};
138
c2f09c75 139static const struct mach_o_segment_name_xlat segsec_names_xlat[] =
154a1ee5
TG
140 {
141 { "__DWARF", dwarf_section_names_xlat },
142 { "__TEXT", text_section_names_xlat },
143 { "__DATA", data_section_names_xlat },
144 { NULL, NULL }
145 };
146
147
148/* Mach-O to bfd names. */
149
8462aec7
TG
150static void
151bfd_mach_o_convert_section_name_to_bfd (bfd *abfd, bfd_mach_o_section *section,
152 char **name, flagword *flags)
154a1ee5
TG
153{
154 const struct mach_o_segment_name_xlat *seg;
155 char *res;
156 unsigned int len;
c2f09c75 157 const char *pfx = "";
154a1ee5 158
8462aec7
TG
159 *name = NULL;
160 *flags = SEC_NO_FLAGS;
161
154a1ee5
TG
162 for (seg = segsec_names_xlat; seg->segname; seg++)
163 {
164 if (strcmp (seg->segname, section->segname) == 0)
165 {
166 const struct mach_o_section_name_xlat *sec;
167
168 for (sec = seg->sections; sec->mach_o_name; sec++)
169 {
170 if (strcmp (sec->mach_o_name, section->sectname) == 0)
171 {
172 len = strlen (sec->bfd_name);
173 res = bfd_alloc (abfd, len + 1);
c2f09c75 174
154a1ee5 175 if (res == NULL)
8462aec7 176 return;
154a1ee5 177 strcpy (res, sec->bfd_name);
8462aec7
TG
178 *name = res;
179 *flags = sec->flags;
180 return;
154a1ee5
TG
181 }
182 }
183 }
184 }
185
c2f09c75 186 len = strlen (section->segname) + 1
154a1ee5
TG
187 + strlen (section->sectname) + 1;
188
c2f09c75
TG
189 /* Put "LC_SEGMENT." prefix if the segment name is weird (ie doesn't start
190 with an underscore. */
191 if (section->segname[0] != '_')
192 {
193 static const char seg_pfx[] = "LC_SEGMENT.";
194
195 pfx = seg_pfx;
196 len += sizeof (seg_pfx) - 1;
197 }
198
154a1ee5
TG
199 res = bfd_alloc (abfd, len);
200 if (res == NULL)
8462aec7 201 return;
c2f09c75 202 snprintf (res, len, "%s%s.%s", pfx, section->segname, section->sectname);
8462aec7 203 *name = res;
154a1ee5
TG
204}
205
c2f09c75 206/* Convert a bfd section name to a Mach-O segment + section name. */
154a1ee5
TG
207
208static void
209bfd_mach_o_convert_section_name_to_mach_o (bfd *abfd ATTRIBUTE_UNUSED,
210 asection *sect,
211 bfd_mach_o_section *section)
212{
213 const struct mach_o_segment_name_xlat *seg;
214 const char *name = bfd_get_section_name (abfd, sect);
215 const char *dot;
216 unsigned int len;
217 unsigned int seglen;
218 unsigned int seclen;
219
c2f09c75
TG
220 /* List of well known names. They all start with a dot. */
221 if (name[0] == '.')
222 for (seg = segsec_names_xlat; seg->segname; seg++)
223 {
224 const struct mach_o_section_name_xlat *sec;
225
226 for (sec = seg->sections; sec->mach_o_name; sec++)
227 {
228 if (strcmp (sec->bfd_name, name) == 0)
229 {
230 strcpy (section->segname, seg->segname);
231 strcpy (section->sectname, sec->mach_o_name);
232 return;
233 }
234 }
235 }
154a1ee5
TG
236
237 /* Strip LC_SEGMENT. prefix. */
238 if (strncmp (name, "LC_SEGMENT.", 11) == 0)
239 name += 11;
240
241 /* Find a dot. */
242 dot = strchr (name, '.');
243 len = strlen (name);
244
245 /* Try to split name into segment and section names. */
246 if (dot && dot != name)
247 {
248 seglen = dot - name;
249 seclen = len - (dot + 1 - name);
250
251 if (seglen < 16 && seclen < 16)
252 {
253 memcpy (section->segname, name, seglen);
254 section->segname[seglen] = 0;
255 memcpy (section->sectname, dot + 1, seclen);
256 section->sectname[seclen] = 0;
257 return;
258 }
259 }
260
261 if (len > 16)
262 len = 16;
263 memcpy (section->segname, name, len);
264 section->segname[len] = 0;
265 memcpy (section->sectname, name, len);
266 section->sectname[len] = 0;
3af9a47b
NC
267}
268
b2b62060
TG
269/* Return the size of an entry for section SEC.
270 Must be called only for symbol pointer section and symbol stubs
271 sections. */
272
273static unsigned int
274bfd_mach_o_section_get_entry_size (bfd *abfd, bfd_mach_o_section *sec)
275{
276 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
277 {
278 case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
279 case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
280 return bfd_mach_o_wide_p (abfd) ? 8 : 4;
281 case BFD_MACH_O_S_SYMBOL_STUBS:
282 return sec->reserved2;
283 default:
284 BFD_FAIL ();
285 return 0;
286 }
287}
288
289/* Return the number of indirect symbols for a section.
290 Must be called only for symbol pointer section and symbol stubs
291 sections. */
292
293static unsigned int
294bfd_mach_o_section_get_nbr_indirect (bfd *abfd, bfd_mach_o_section *sec)
295{
296 unsigned int elsz;
297
298 elsz = bfd_mach_o_section_get_entry_size (abfd, sec);
299 if (elsz == 0)
300 return 0;
301 else
302 return sec->size / elsz;
303}
304
305
3af9a47b
NC
306/* Copy any private info we understand from the input symbol
307 to the output symbol. */
308
154a1ee5 309bfd_boolean
116c20d2
NC
310bfd_mach_o_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
311 asymbol *isymbol ATTRIBUTE_UNUSED,
312 bfd *obfd ATTRIBUTE_UNUSED,
313 asymbol *osymbol ATTRIBUTE_UNUSED)
3af9a47b 314{
b34976b6 315 return TRUE;
3af9a47b
NC
316}
317
318/* Copy any private info we understand from the input section
319 to the output section. */
320
154a1ee5 321bfd_boolean
116c20d2
NC
322bfd_mach_o_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
323 asection *isection ATTRIBUTE_UNUSED,
324 bfd *obfd ATTRIBUTE_UNUSED,
325 asection *osection ATTRIBUTE_UNUSED)
3af9a47b 326{
b34976b6 327 return TRUE;
3af9a47b
NC
328}
329
330/* Copy any private info we understand from the input bfd
331 to the output bfd. */
332
154a1ee5 333bfd_boolean
116c20d2 334bfd_mach_o_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
3af9a47b 335{
154a1ee5
TG
336 if (bfd_get_flavour (ibfd) != bfd_target_mach_o_flavour
337 || bfd_get_flavour (obfd) != bfd_target_mach_o_flavour)
338 return TRUE;
339
3af9a47b
NC
340 BFD_ASSERT (bfd_mach_o_valid (ibfd));
341 BFD_ASSERT (bfd_mach_o_valid (obfd));
342
154a1ee5
TG
343 /* FIXME: copy commands. */
344
b34976b6 345 return TRUE;
3af9a47b
NC
346}
347
046b007d 348/* Count the total number of symbols. */
154a1ee5 349
3af9a47b 350static long
116c20d2 351bfd_mach_o_count_symbols (bfd *abfd)
3af9a47b 352{
046b007d 353 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b 354
046b007d
TG
355 if (mdata->symtab == NULL)
356 return 0;
357 return mdata->symtab->nsyms;
3af9a47b
NC
358}
359
154a1ee5 360long
116c20d2 361bfd_mach_o_get_symtab_upper_bound (bfd *abfd)
3af9a47b
NC
362{
363 long nsyms = bfd_mach_o_count_symbols (abfd);
364
3af9a47b
NC
365 return ((nsyms + 1) * sizeof (asymbol *));
366}
367
154a1ee5 368long
116c20d2 369bfd_mach_o_canonicalize_symtab (bfd *abfd, asymbol **alocation)
3af9a47b 370{
046b007d 371 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b 372 long nsyms = bfd_mach_o_count_symbols (abfd);
046b007d
TG
373 bfd_mach_o_symtab_command *sym = mdata->symtab;
374 unsigned long j;
3af9a47b
NC
375
376 if (nsyms < 0)
377 return nsyms;
378
092d27ff
TG
379 if (nsyms == 0)
380 {
381 /* Do not try to read symbols if there are none. */
382 alocation[0] = NULL;
383 return 0;
384 }
385
ab273af8 386 if (bfd_mach_o_read_symtab_symbols (abfd) != 0)
3af9a47b 387 {
4a97a0e5 388 (*_bfd_error_handler) (_("bfd_mach_o_canonicalize_symtab: unable to load symbols"));
046b007d
TG
389 return 0;
390 }
3af9a47b 391
046b007d 392 BFD_ASSERT (sym->symbols != NULL);
3af9a47b 393
046b007d
TG
394 for (j = 0; j < sym->nsyms; j++)
395 alocation[j] = &sym->symbols[j].symbol;
3af9a47b 396
046b007d 397 alocation[j] = NULL;
a95a4550 398
3af9a47b
NC
399 return nsyms;
400}
401
b2b62060
TG
402long
403bfd_mach_o_get_synthetic_symtab (bfd *abfd,
404 long symcount ATTRIBUTE_UNUSED,
405 asymbol **syms ATTRIBUTE_UNUSED,
406 long dynsymcount ATTRIBUTE_UNUSED,
407 asymbol **dynsyms ATTRIBUTE_UNUSED,
408 asymbol **ret)
409{
410 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
411 bfd_mach_o_dysymtab_command *dysymtab = mdata->dysymtab;
412 bfd_mach_o_symtab_command *symtab = mdata->symtab;
413 asymbol *s;
414 unsigned long count, i, j, n;
415 size_t size;
416 char *names;
417 char *nul_name;
418
419 *ret = NULL;
420
421 if (dysymtab == NULL || symtab == NULL || symtab->symbols == NULL)
422 return 0;
423
424 if (dysymtab->nindirectsyms == 0)
425 return 0;
426
427 count = dysymtab->nindirectsyms;
428 size = count * sizeof (asymbol) + 1;
429
430 for (j = 0; j < count; j++)
431 {
432 unsigned int isym = dysymtab->indirect_syms[j];
433
434 if (isym < symtab->nsyms && symtab->symbols[isym].symbol.name)
435 size += strlen (symtab->symbols[isym].symbol.name) + sizeof ("$stub");
436 }
437
438 s = *ret = (asymbol *) bfd_malloc (size);
439 if (s == NULL)
440 return -1;
441 names = (char *) (s + count);
442 nul_name = names;
443 *names++ = 0;
444
445 n = 0;
446 for (i = 0; i < mdata->nsects; i++)
447 {
448 bfd_mach_o_section *sec = mdata->sections[i];
91d6fa6a 449 unsigned int first, last;
b2b62060
TG
450 bfd_vma addr;
451 bfd_vma entry_size;
452
453 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
454 {
455 case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
456 case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
457 case BFD_MACH_O_S_SYMBOL_STUBS:
458 first = sec->reserved1;
459 last = first + bfd_mach_o_section_get_nbr_indirect (abfd, sec);
460 addr = sec->addr;
461 entry_size = bfd_mach_o_section_get_entry_size (abfd, sec);
462 for (j = first; j < last; j++)
463 {
464 unsigned int isym = dysymtab->indirect_syms[j];
465
466 s->flags = BSF_GLOBAL | BSF_SYNTHETIC;
467 s->section = sec->bfdsection;
468 s->value = addr - sec->addr;
469 s->udata.p = NULL;
470
471 if (isym < symtab->nsyms
472 && symtab->symbols[isym].symbol.name)
473 {
474 const char *sym = symtab->symbols[isym].symbol.name;
475 size_t len;
476
477 s->name = names;
478 len = strlen (sym);
479 memcpy (names, sym, len);
480 names += len;
481 memcpy (names, "$stub", sizeof ("$stub"));
482 names += sizeof ("$stub");
483 }
484 else
485 s->name = nul_name;
486
487 addr += entry_size;
488 s++;
489 n++;
490 }
491 break;
492 default:
493 break;
494 }
495 }
496
497 return n;
498}
499
154a1ee5 500void
116c20d2
NC
501bfd_mach_o_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
502 asymbol *symbol,
503 symbol_info *ret)
3af9a47b
NC
504{
505 bfd_symbol_info (symbol, ret);
506}
507
154a1ee5 508void
116c20d2 509bfd_mach_o_print_symbol (bfd *abfd,
91d6fa6a 510 void * afile,
116c20d2
NC
511 asymbol *symbol,
512 bfd_print_symbol_type how)
3af9a47b
NC
513{
514 FILE *file = (FILE *) afile;
15e1c58a 515 const char *name;
92bc0e80 516 bfd_mach_o_asymbol *asym = (bfd_mach_o_asymbol *)symbol;
3af9a47b
NC
517
518 switch (how)
519 {
520 case bfd_print_symbol_name:
521 fprintf (file, "%s", symbol->name);
522 break;
523 default:
91d6fa6a 524 bfd_print_symbol_vandf (abfd, (void *) file, symbol);
92bc0e80
TG
525 if (asym->n_type & BFD_MACH_O_N_STAB)
526 name = bfd_get_stab_name (asym->n_type);
15e1c58a 527 else
92bc0e80 528 switch (asym->n_type & BFD_MACH_O_N_TYPE)
15e1c58a
TG
529 {
530 case BFD_MACH_O_N_UNDF:
531 name = "UND";
532 break;
533 case BFD_MACH_O_N_ABS:
534 name = "ABS";
535 break;
536 case BFD_MACH_O_N_INDR:
537 name = "INDR";
538 break;
539 case BFD_MACH_O_N_PBUD:
540 name = "PBUD";
541 break;
542 case BFD_MACH_O_N_SECT:
543 name = "SECT";
544 break;
545 default:
546 name = "???";
547 break;
548 }
549 if (name == NULL)
550 name = "";
92bc0e80
TG
551 fprintf (file, " %02x %-6s %02x %04x",
552 asym->n_type, name, asym->n_sect, asym->n_desc);
553 if ((asym->n_type & BFD_MACH_O_N_STAB) == 0
554 && (asym->n_type & BFD_MACH_O_N_TYPE) == BFD_MACH_O_N_SECT)
15e1c58a
TG
555 fprintf (file, " %-5s", symbol->section->name);
556 fprintf (file, " %s", symbol->name);
3af9a47b
NC
557 }
558}
559
560static void
116c20d2
NC
561bfd_mach_o_convert_architecture (bfd_mach_o_cpu_type mtype,
562 bfd_mach_o_cpu_subtype msubtype ATTRIBUTE_UNUSED,
563 enum bfd_architecture *type,
564 unsigned long *subtype)
3af9a47b
NC
565{
566 *subtype = bfd_arch_unknown;
567
568 switch (mtype)
569 {
570 case BFD_MACH_O_CPU_TYPE_VAX: *type = bfd_arch_vax; break;
571 case BFD_MACH_O_CPU_TYPE_MC680x0: *type = bfd_arch_m68k; break;
1e8a024a
TG
572 case BFD_MACH_O_CPU_TYPE_I386:
573 *type = bfd_arch_i386;
574 *subtype = bfd_mach_i386_i386;
575 break;
576 case BFD_MACH_O_CPU_TYPE_X86_64:
577 *type = bfd_arch_i386;
578 *subtype = bfd_mach_x86_64;
579 break;
3af9a47b
NC
580 case BFD_MACH_O_CPU_TYPE_MIPS: *type = bfd_arch_mips; break;
581 case BFD_MACH_O_CPU_TYPE_MC98000: *type = bfd_arch_m98k; break;
582 case BFD_MACH_O_CPU_TYPE_HPPA: *type = bfd_arch_hppa; break;
583 case BFD_MACH_O_CPU_TYPE_ARM: *type = bfd_arch_arm; break;
584 case BFD_MACH_O_CPU_TYPE_MC88000: *type = bfd_arch_m88k; break;
1e8a024a
TG
585 case BFD_MACH_O_CPU_TYPE_SPARC:
586 *type = bfd_arch_sparc;
587 *subtype = bfd_mach_sparc;
588 break;
3af9a47b
NC
589 case BFD_MACH_O_CPU_TYPE_I860: *type = bfd_arch_i860; break;
590 case BFD_MACH_O_CPU_TYPE_ALPHA: *type = bfd_arch_alpha; break;
1e8a024a
TG
591 case BFD_MACH_O_CPU_TYPE_POWERPC:
592 *type = bfd_arch_powerpc;
c2f09c75 593 *subtype = bfd_mach_ppc;
1e8a024a
TG
594 break;
595 case BFD_MACH_O_CPU_TYPE_POWERPC_64:
596 *type = bfd_arch_powerpc;
c2f09c75 597 *subtype = bfd_mach_ppc64;
1e8a024a 598 break;
3af9a47b 599 default:
1e8a024a
TG
600 *type = bfd_arch_unknown;
601 break;
3af9a47b
NC
602 }
603}
a95a4550 604
154a1ee5 605static bfd_boolean
116c20d2
NC
606bfd_mach_o_write_header (bfd *abfd, bfd_mach_o_header *header)
607{
1e8a024a
TG
608 unsigned char buf[32];
609 unsigned int size;
610
c2f09c75 611 size = mach_o_wide_p (header) ?
154a1ee5 612 BFD_MACH_O_HEADER_64_SIZE : BFD_MACH_O_HEADER_SIZE;
116c20d2
NC
613
614 bfd_h_put_32 (abfd, header->magic, buf + 0);
615 bfd_h_put_32 (abfd, header->cputype, buf + 4);
616 bfd_h_put_32 (abfd, header->cpusubtype, buf + 8);
617 bfd_h_put_32 (abfd, header->filetype, buf + 12);
618 bfd_h_put_32 (abfd, header->ncmds, buf + 16);
619 bfd_h_put_32 (abfd, header->sizeofcmds, buf + 20);
620 bfd_h_put_32 (abfd, header->flags, buf + 24);
621
c2f09c75 622 if (mach_o_wide_p (header))
1e8a024a
TG
623 bfd_h_put_32 (abfd, header->reserved, buf + 28);
624
c2f09c75 625 if (bfd_seek (abfd, 0, SEEK_SET) != 0
91d6fa6a 626 || bfd_bwrite ((void *) buf, size, abfd) != size)
154a1ee5 627 return FALSE;
116c20d2 628
154a1ee5 629 return TRUE;
116c20d2
NC
630}
631
632static int
ab273af8 633bfd_mach_o_write_thread (bfd *abfd, bfd_mach_o_load_command *command)
116c20d2
NC
634{
635 bfd_mach_o_thread_command *cmd = &command->command.thread;
636 unsigned int i;
637 unsigned char buf[8];
92bc0e80 638 unsigned int offset;
116c20d2
NC
639
640 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
641 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
642
643 offset = 8;
116c20d2
NC
644 for (i = 0; i < cmd->nflavours; i++)
645 {
646 BFD_ASSERT ((cmd->flavours[i].size % 4) == 0);
647 BFD_ASSERT (cmd->flavours[i].offset == (command->offset + offset + 8));
648
649 bfd_h_put_32 (abfd, cmd->flavours[i].flavour, buf);
650 bfd_h_put_32 (abfd, (cmd->flavours[i].size / 4), buf + 4);
651
c2f09c75 652 if (bfd_seek (abfd, command->offset + offset, SEEK_SET) != 0
91d6fa6a 653 || bfd_bwrite ((void *) buf, 8, abfd) != 8)
116c20d2
NC
654 return -1;
655
656 offset += cmd->flavours[i].size + 8;
657 }
658
659 return 0;
660}
661
92bc0e80
TG
662long
663bfd_mach_o_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
664 asection *asect)
665{
666 return (asect->reloc_count + 1) * sizeof (arelent *);
667}
668
b32e07d7
TG
669static int
670bfd_mach_o_canonicalize_one_reloc (bfd *abfd, char *buf,
671 arelent *res, asymbol **syms)
92bc0e80 672{
046b007d 673 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
92bc0e80 674 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
b32e07d7
TG
675 bfd_mach_o_reloc_info reloc;
676 bfd_vma addr;
677 bfd_vma symnum;
678 asymbol **sym;
679
680 addr = bfd_get_32 (abfd, buf + 0);
681 symnum = bfd_get_32 (abfd, buf + 4);
682
683 if (addr & BFD_MACH_O_SR_SCATTERED)
684 {
685 unsigned int j;
686
687 /* Scattered relocation.
688 Extract section and offset from r_value. */
689 res->sym_ptr_ptr = NULL;
690 res->addend = 0;
691 for (j = 0; j < mdata->nsects; j++)
692 {
693 bfd_mach_o_section *sect = mdata->sections[j];
694 if (symnum >= sect->addr && symnum < sect->addr + sect->size)
695 {
696 res->sym_ptr_ptr = sect->bfdsection->symbol_ptr_ptr;
697 res->addend = symnum - sect->addr;
698 break;
699 }
700 }
701 res->address = BFD_MACH_O_GET_SR_ADDRESS (addr);
702 reloc.r_type = BFD_MACH_O_GET_SR_TYPE (addr);
703 reloc.r_length = BFD_MACH_O_GET_SR_LENGTH (addr);
704 reloc.r_pcrel = addr & BFD_MACH_O_SR_PCREL;
705 reloc.r_scattered = 1;
706 }
707 else
708 {
709 unsigned int num = BFD_MACH_O_GET_R_SYMBOLNUM (symnum);
710 res->addend = 0;
711 res->address = addr;
712 if (symnum & BFD_MACH_O_R_EXTERN)
06988dfc
TG
713 {
714 sym = syms + num;
715 reloc.r_extern = 1;
716 }
b32e07d7
TG
717 else
718 {
719 BFD_ASSERT (num != 0);
720 BFD_ASSERT (num <= mdata->nsects);
721 sym = mdata->sections[num - 1]->bfdsection->symbol_ptr_ptr;
1523fa24
TG
722 /* For a symbol defined in section S, the addend (stored in the
723 binary) contains the address of the section. To comply with
724 bfd conventio, substract the section address.
725 Use the address from the header, so that the user can modify
726 the vma of the section. */
727 res->addend = -mdata->sections[num - 1]->addr;
06988dfc 728 reloc.r_extern = 0;
b32e07d7
TG
729 }
730 res->sym_ptr_ptr = sym;
731 reloc.r_type = BFD_MACH_O_GET_R_TYPE (symnum);
732 reloc.r_length = BFD_MACH_O_GET_R_LENGTH (symnum);
733 reloc.r_pcrel = (symnum & BFD_MACH_O_R_PCREL) ? 1 : 0;
734 reloc.r_scattered = 0;
735 }
736
737 if (!(*bed->_bfd_mach_o_swap_reloc_in)(res, &reloc))
738 return -1;
739 return 0;
740}
741
742static int
743bfd_mach_o_canonicalize_relocs (bfd *abfd, unsigned long filepos,
744 unsigned long count,
745 arelent *res, asymbol **syms)
746{
92bc0e80 747 unsigned long i;
92bc0e80
TG
748 char *native_relocs;
749 bfd_size_type native_size;
750
92bc0e80 751 /* Allocate and read relocs. */
b32e07d7 752 native_size = count * BFD_MACH_O_RELENT_SIZE;
92bc0e80
TG
753 native_relocs = bfd_malloc (native_size);
754 if (native_relocs == NULL)
755 return -1;
756
b32e07d7 757 if (bfd_seek (abfd, filepos, SEEK_SET) != 0
92bc0e80 758 || bfd_bread (native_relocs, native_size, abfd) != native_size)
b32e07d7
TG
759 goto err;
760
761 for (i = 0; i < count; i++)
92bc0e80 762 {
b32e07d7
TG
763 char *buf = native_relocs + BFD_MACH_O_RELENT_SIZE * i;
764
765 if (bfd_mach_o_canonicalize_one_reloc (abfd, buf, &res[i], syms) < 0)
766 goto err;
92bc0e80 767 }
b32e07d7
TG
768 free (native_relocs);
769 return i;
770 err:
771 free (native_relocs);
772 return -1;
773}
774
775long
776bfd_mach_o_canonicalize_reloc (bfd *abfd, asection *asect,
777 arelent **rels, asymbol **syms)
778{
779 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
780 unsigned long i;
781 arelent *res;
782
783 if (asect->reloc_count == 0)
784 return 0;
785
786 /* No need to go further if we don't know how to read relocs. */
787 if (bed->_bfd_mach_o_swap_reloc_in == NULL)
788 return 0;
92bc0e80
TG
789
790 res = bfd_malloc (asect->reloc_count * sizeof (arelent));
791 if (res == NULL)
b32e07d7
TG
792 return -1;
793
794 if (bfd_mach_o_canonicalize_relocs (abfd, asect->rel_filepos,
795 asect->reloc_count, res, syms) < 0)
92bc0e80 796 {
b32e07d7 797 free (res);
92bc0e80
TG
798 return -1;
799 }
800
801 for (i = 0; i < asect->reloc_count; i++)
b32e07d7
TG
802 rels[i] = &res[i];
803 rels[i] = NULL;
804 asect->relocation = res;
92bc0e80 805
b32e07d7
TG
806 return i;
807}
92bc0e80 808
b32e07d7
TG
809long
810bfd_mach_o_get_dynamic_reloc_upper_bound (bfd *abfd)
811{
812 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
92bc0e80 813
b32e07d7
TG
814 if (mdata->dysymtab == NULL)
815 return 1;
816 return (mdata->dysymtab->nextrel + mdata->dysymtab->nlocrel)
817 * sizeof (arelent *);
818}
92bc0e80 819
b32e07d7
TG
820long
821bfd_mach_o_canonicalize_dynamic_reloc (bfd *abfd, arelent **rels,
822 struct bfd_symbol **syms)
823{
824 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
825 bfd_mach_o_dysymtab_command *dysymtab = mdata->dysymtab;
826 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
827 unsigned long i;
828 arelent *res;
829
830 if (dysymtab == NULL)
831 return 0;
832 if (dysymtab->nextrel == 0 && dysymtab->nlocrel == 0)
833 return 0;
834
835 /* No need to go further if we don't know how to read relocs. */
836 if (bed->_bfd_mach_o_swap_reloc_in == NULL)
837 return 0;
838
839 res = bfd_malloc ((dysymtab->nextrel + dysymtab->nlocrel) * sizeof (arelent));
840 if (res == NULL)
841 return -1;
842
843 if (bfd_mach_o_canonicalize_relocs (abfd, dysymtab->extreloff,
844 dysymtab->nextrel, res, syms) < 0)
845 {
846 free (res);
847 return -1;
92bc0e80 848 }
b32e07d7
TG
849
850 if (bfd_mach_o_canonicalize_relocs (abfd, dysymtab->locreloff,
851 dysymtab->nlocrel,
852 res + dysymtab->nextrel, syms) < 0)
853 {
854 free (res);
855 return -1;
856 }
857
858 for (i = 0; i < dysymtab->nextrel + dysymtab->nlocrel; i++)
859 rels[i] = &res[i];
860 rels[i] = NULL;
92bc0e80
TG
861 return i;
862}
863
864static bfd_boolean
ab273af8 865bfd_mach_o_write_relocs (bfd *abfd, bfd_mach_o_section *section)
92bc0e80 866{
046b007d 867 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
92bc0e80
TG
868 unsigned int i;
869 arelent **entries;
870 asection *sec;
871 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
872
873 sec = section->bfdsection;
874 if (sec->reloc_count == 0)
875 return TRUE;
876
877 if (bed->_bfd_mach_o_swap_reloc_out == NULL)
878 return TRUE;
879
880 /* Allocate relocation room. */
881 mdata->filelen = FILE_ALIGN(mdata->filelen, 2);
882 section->nreloc = sec->reloc_count;
883 sec->rel_filepos = mdata->filelen;
884 section->reloff = sec->rel_filepos;
885 mdata->filelen += sec->reloc_count * BFD_MACH_O_RELENT_SIZE;
886
887 if (bfd_seek (abfd, section->reloff, SEEK_SET) != 0)
888 return FALSE;
889
890 /* Convert and write. */
891 entries = section->bfdsection->orelocation;
892 for (i = 0; i < section->nreloc; i++)
893 {
894 arelent *rel = entries[i];
895 char buf[8];
896 bfd_mach_o_reloc_info info, *pinfo = &info;
897
898 /* Convert relocation to an intermediate representation. */
899 if (!(*bed->_bfd_mach_o_swap_reloc_out) (rel, pinfo))
900 return FALSE;
901
902 /* Lower the relocation info. */
903 if (pinfo->r_scattered)
904 {
905 unsigned long v;
906
907 v = BFD_MACH_O_SR_SCATTERED
908 | (pinfo->r_pcrel ? BFD_MACH_O_SR_PCREL : 0)
909 | BFD_MACH_O_SET_SR_LENGTH(pinfo->r_length)
910 | BFD_MACH_O_SET_SR_TYPE(pinfo->r_type)
911 | BFD_MACH_O_SET_SR_ADDRESS(pinfo->r_address);
912 bfd_put_32 (abfd, v, buf);
913 bfd_put_32 (abfd, pinfo->r_value, buf + 4);
914 }
915 else
916 {
917 unsigned long v;
918
919 bfd_put_32 (abfd, pinfo->r_address, buf);
920 v = BFD_MACH_O_SET_R_SYMBOLNUM (pinfo->r_value)
921 | (pinfo->r_pcrel ? BFD_MACH_O_R_PCREL : 0)
922 | BFD_MACH_O_SET_R_LENGTH (pinfo->r_length)
923 | (pinfo->r_extern ? BFD_MACH_O_R_EXTERN : 0)
924 | BFD_MACH_O_SET_R_TYPE (pinfo->r_type);
925 bfd_put_32 (abfd, v, buf + 4);
926 }
927
91d6fa6a 928 if (bfd_bwrite ((void *) buf, BFD_MACH_O_RELENT_SIZE, abfd)
92bc0e80
TG
929 != BFD_MACH_O_RELENT_SIZE)
930 return FALSE;
931 }
932 return TRUE;
933}
934
116c20d2 935static int
ab273af8 936bfd_mach_o_write_section_32 (bfd *abfd, bfd_mach_o_section *section)
116c20d2 937{
154a1ee5 938 unsigned char buf[BFD_MACH_O_SECTION_SIZE];
116c20d2
NC
939
940 memcpy (buf, section->sectname, 16);
941 memcpy (buf + 16, section->segname, 16);
942 bfd_h_put_32 (abfd, section->addr, buf + 32);
943 bfd_h_put_32 (abfd, section->size, buf + 36);
944 bfd_h_put_32 (abfd, section->offset, buf + 40);
945 bfd_h_put_32 (abfd, section->align, buf + 44);
946 bfd_h_put_32 (abfd, section->reloff, buf + 48);
947 bfd_h_put_32 (abfd, section->nreloc, buf + 52);
948 bfd_h_put_32 (abfd, section->flags, buf + 56);
1e8a024a
TG
949 bfd_h_put_32 (abfd, section->reserved1, buf + 60);
950 bfd_h_put_32 (abfd, section->reserved2, buf + 64);
116c20d2 951
91d6fa6a 952 if (bfd_bwrite ((void *) buf, BFD_MACH_O_SECTION_SIZE, abfd)
92bc0e80 953 != BFD_MACH_O_SECTION_SIZE)
116c20d2
NC
954 return -1;
955
956 return 0;
957}
958
959static int
ab273af8 960bfd_mach_o_write_section_64 (bfd *abfd, bfd_mach_o_section *section)
116c20d2 961{
154a1ee5 962 unsigned char buf[BFD_MACH_O_SECTION_64_SIZE];
116c20d2 963
1e8a024a
TG
964 memcpy (buf, section->sectname, 16);
965 memcpy (buf + 16, section->segname, 16);
966 bfd_h_put_64 (abfd, section->addr, buf + 32);
967 bfd_h_put_64 (abfd, section->size, buf + 40);
968 bfd_h_put_32 (abfd, section->offset, buf + 48);
969 bfd_h_put_32 (abfd, section->align, buf + 52);
970 bfd_h_put_32 (abfd, section->reloff, buf + 56);
971 bfd_h_put_32 (abfd, section->nreloc, buf + 60);
972 bfd_h_put_32 (abfd, section->flags, buf + 64);
973 bfd_h_put_32 (abfd, section->reserved1, buf + 68);
974 bfd_h_put_32 (abfd, section->reserved2, buf + 72);
975 bfd_h_put_32 (abfd, section->reserved3, buf + 76);
116c20d2 976
91d6fa6a 977 if (bfd_bwrite ((void *) buf, BFD_MACH_O_SECTION_64_SIZE, abfd)
92bc0e80 978 != BFD_MACH_O_SECTION_64_SIZE)
116c20d2
NC
979 return -1;
980
1e8a024a
TG
981 return 0;
982}
983
984static int
ab273af8 985bfd_mach_o_write_segment_32 (bfd *abfd, bfd_mach_o_load_command *command)
1e8a024a 986{
c2f09c75 987 unsigned char buf[BFD_MACH_O_LC_SEGMENT_SIZE];
1e8a024a
TG
988 bfd_mach_o_segment_command *seg = &command->command.segment;
989 unsigned long i;
990
c2f09c75
TG
991 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
992
92bc0e80 993 for (i = 0; i < seg->nsects; i++)
ab273af8 994 if (!bfd_mach_o_write_relocs (abfd, &seg->sections[i]))
92bc0e80 995 return -1;
c2f09c75 996
92bc0e80 997 memcpy (buf, seg->segname, 16);
c2f09c75
TG
998 bfd_h_put_32 (abfd, seg->vmaddr, buf + 16);
999 bfd_h_put_32 (abfd, seg->vmsize, buf + 20);
1000 bfd_h_put_32 (abfd, seg->fileoff, buf + 24);
1001 bfd_h_put_32 (abfd, seg->filesize, buf + 28);
1002 bfd_h_put_32 (abfd, seg->maxprot, buf + 32);
1003 bfd_h_put_32 (abfd, seg->initprot, buf + 36);
1004 bfd_h_put_32 (abfd, seg->nsects, buf + 40);
1005 bfd_h_put_32 (abfd, seg->flags, buf + 44);
1006
1007 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 1008 || (bfd_bwrite ((void *) buf, BFD_MACH_O_LC_SEGMENT_SIZE - 8, abfd)
92bc0e80 1009 != BFD_MACH_O_LC_SEGMENT_SIZE - 8))
c2f09c75 1010 return -1;
1e8a024a 1011
116c20d2 1012 for (i = 0; i < seg->nsects; i++)
ab273af8 1013 if (bfd_mach_o_write_section_32 (abfd, &seg->sections[i]))
92bc0e80 1014 return -1;
1e8a024a 1015
116c20d2
NC
1016 return 0;
1017}
1018
1e8a024a 1019static int
ab273af8 1020bfd_mach_o_write_segment_64 (bfd *abfd, bfd_mach_o_load_command *command)
1e8a024a 1021{
c2f09c75
TG
1022 unsigned char buf[BFD_MACH_O_LC_SEGMENT_64_SIZE];
1023 bfd_mach_o_segment_command *seg = &command->command.segment;
1024 unsigned long i;
1025
1026 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT_64);
1027
92bc0e80 1028 for (i = 0; i < seg->nsects; i++)
ab273af8 1029 if (!bfd_mach_o_write_relocs (abfd, &seg->sections[i]))
92bc0e80 1030 return -1;
c2f09c75 1031
92bc0e80 1032 memcpy (buf, seg->segname, 16);
c2f09c75
TG
1033 bfd_h_put_64 (abfd, seg->vmaddr, buf + 16);
1034 bfd_h_put_64 (abfd, seg->vmsize, buf + 24);
1035 bfd_h_put_64 (abfd, seg->fileoff, buf + 32);
1036 bfd_h_put_64 (abfd, seg->filesize, buf + 40);
1037 bfd_h_put_32 (abfd, seg->maxprot, buf + 48);
1038 bfd_h_put_32 (abfd, seg->initprot, buf + 52);
1039 bfd_h_put_32 (abfd, seg->nsects, buf + 56);
1040 bfd_h_put_32 (abfd, seg->flags, buf + 60);
1041
1042 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 1043 || (bfd_bwrite ((void *) buf, BFD_MACH_O_LC_SEGMENT_64_SIZE - 8, abfd)
92bc0e80 1044 != BFD_MACH_O_LC_SEGMENT_64_SIZE - 8))
c2f09c75
TG
1045 return -1;
1046
1047 for (i = 0; i < seg->nsects; i++)
ab273af8 1048 if (bfd_mach_o_write_section_64 (abfd, &seg->sections[i]))
92bc0e80 1049 return -1;
c2f09c75 1050
c2f09c75 1051 return 0;
1e8a024a
TG
1052}
1053
c2f09c75 1054static bfd_boolean
ab273af8 1055bfd_mach_o_write_symtab (bfd *abfd, bfd_mach_o_load_command *command)
116c20d2 1056{
046b007d 1057 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
116c20d2 1058 bfd_mach_o_symtab_command *sym = &command->command.symtab;
c2f09c75 1059 unsigned char buf[16];
116c20d2 1060 unsigned long i;
c2f09c75 1061 unsigned int wide = bfd_mach_o_wide_p (abfd);
046b007d 1062 unsigned int symlen = wide ? BFD_MACH_O_NLIST_64_SIZE : BFD_MACH_O_NLIST_SIZE;
c2f09c75
TG
1063 struct bfd_strtab_hash *strtab;
1064 asymbol **symbols = bfd_get_outsymbols (abfd);
1065
1066 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
1067
1068 /* Write the symbols first. */
92bc0e80
TG
1069 mdata->filelen = FILE_ALIGN(mdata->filelen, wide ? 3 : 2);
1070 sym->symoff = mdata->filelen;
c2f09c75
TG
1071 if (bfd_seek (abfd, sym->symoff, SEEK_SET) != 0)
1072 return FALSE;
1073
1074 sym->nsyms = bfd_get_symcount (abfd);
92bc0e80 1075 mdata->filelen += sym->nsyms * symlen;
c2f09c75
TG
1076
1077 strtab = _bfd_stringtab_init ();
1078 if (strtab == NULL)
1079 return FALSE;
116c20d2
NC
1080
1081 for (i = 0; i < sym->nsyms; i++)
1082 {
91d6fa6a 1083 bfd_size_type str_index;
92bc0e80 1084 bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i];
c2f09c75 1085
92bc0e80 1086 /* Compute name index. */
c2f09c75 1087 /* An index of 0 always means the empty string. */
92bc0e80 1088 if (s->symbol.name == 0 || s->symbol.name[0] == '\0')
91d6fa6a 1089 str_index = 0;
c2f09c75
TG
1090 else
1091 {
91d6fa6a
NC
1092 str_index = _bfd_stringtab_add (strtab, s->symbol.name, TRUE, FALSE);
1093 if (str_index == (bfd_size_type) -1)
c2f09c75
TG
1094 goto err;
1095 }
91d6fa6a 1096 bfd_h_put_32 (abfd, str_index, buf);
92bc0e80
TG
1097 bfd_h_put_8 (abfd, s->n_type, buf + 4);
1098 bfd_h_put_8 (abfd, s->n_sect, buf + 5);
1099 bfd_h_put_16 (abfd, s->n_desc, buf + 6);
c2f09c75 1100 if (wide)
92bc0e80 1101 bfd_h_put_64 (abfd, s->symbol.section->vma + s->symbol.value, buf + 8);
c2f09c75 1102 else
92bc0e80 1103 bfd_h_put_32 (abfd, s->symbol.section->vma + s->symbol.value, buf + 8);
116c20d2 1104
91d6fa6a 1105 if (bfd_bwrite ((void *) buf, symlen, abfd) != symlen)
c2f09c75 1106 goto err;
116c20d2 1107 }
c2f09c75 1108 sym->strsize = _bfd_stringtab_size (strtab);
92bc0e80
TG
1109 sym->stroff = mdata->filelen;
1110 mdata->filelen += sym->strsize;
116c20d2 1111
c2f09c75
TG
1112 if (_bfd_stringtab_emit (abfd, strtab) != TRUE)
1113 goto err;
1114 _bfd_stringtab_free (strtab);
116c20d2 1115
c2f09c75
TG
1116 /* The command. */
1117 bfd_h_put_32 (abfd, sym->symoff, buf);
1118 bfd_h_put_32 (abfd, sym->nsyms, buf + 4);
1119 bfd_h_put_32 (abfd, sym->stroff, buf + 8);
1120 bfd_h_put_32 (abfd, sym->strsize, buf + 12);
116c20d2 1121
c2f09c75 1122 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 1123 || bfd_bwrite ((void *) buf, 16, abfd) != 16)
c2f09c75 1124 return FALSE;
116c20d2 1125
c2f09c75 1126 return TRUE;
116c20d2 1127
c2f09c75
TG
1128 err:
1129 _bfd_stringtab_free (strtab);
1130 return FALSE;
116c20d2
NC
1131}
1132
92bc0e80
TG
1133/* Process the symbols and generate Mach-O specific fields.
1134 Number them. */
1135
1136static bfd_boolean
1137bfd_mach_o_mangle_symbols (bfd *abfd)
1138{
1139 unsigned long i;
1140 asymbol **symbols = bfd_get_outsymbols (abfd);
1141
1142 for (i = 0; i < bfd_get_symcount (abfd); i++)
1143 {
1144 bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i];
1145
1146 if (s->n_type == BFD_MACH_O_N_UNDF && !(s->symbol.flags & BSF_DEBUGGING))
1147 {
1148 /* As genuine Mach-O symbols type shouldn't be N_UNDF (undefined
1149 symbols should be N_UNDEF | N_EXT), we suppose the back-end
1150 values haven't been set. */
1151 if (s->symbol.section == bfd_abs_section_ptr)
1152 s->n_type = BFD_MACH_O_N_ABS;
1153 else if (s->symbol.section == bfd_und_section_ptr)
1154 {
1155 s->n_type = BFD_MACH_O_N_UNDF;
1156 if (s->symbol.flags & BSF_WEAK)
1157 s->n_desc |= BFD_MACH_O_N_WEAK_REF;
1158 }
1159 else if (s->symbol.section == bfd_com_section_ptr)
1160 s->n_type = BFD_MACH_O_N_UNDF | BFD_MACH_O_N_EXT;
1161 else
1162 s->n_type = BFD_MACH_O_N_SECT;
1163
1164 if (s->symbol.flags & BSF_GLOBAL)
1165 s->n_type |= BFD_MACH_O_N_EXT;
1166 }
1167
1168 /* Compute section index. */
1169 if (s->symbol.section != bfd_abs_section_ptr
1170 && s->symbol.section != bfd_und_section_ptr
1171 && s->symbol.section != bfd_com_section_ptr)
1172 s->n_sect = s->symbol.section->target_index;
1173
1174 /* Number symbols. */
1175 s->symbol.udata.i = i;
1176 }
1177 return TRUE;
1178}
1179
154a1ee5 1180bfd_boolean
116c20d2 1181bfd_mach_o_write_contents (bfd *abfd)
3af9a47b
NC
1182{
1183 unsigned int i;
046b007d 1184 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b 1185
92bc0e80
TG
1186 if (mdata->header.ncmds == 0)
1187 if (!bfd_mach_o_build_commands (abfd))
1188 return FALSE;
1189
3af9a47b 1190 /* Now write header information. */
c2f09c75
TG
1191 if (mdata->header.filetype == 0)
1192 {
1193 if (abfd->flags & EXEC_P)
1194 mdata->header.filetype = BFD_MACH_O_MH_EXECUTE;
1195 else if (abfd->flags & DYNAMIC)
1196 mdata->header.filetype = BFD_MACH_O_MH_DYLIB;
1197 else
1198 mdata->header.filetype = BFD_MACH_O_MH_OBJECT;
1199 }
154a1ee5 1200 if (!bfd_mach_o_write_header (abfd, &mdata->header))
b34976b6 1201 return FALSE;
3af9a47b 1202
92bc0e80
TG
1203 /* Assign a number to each symbols. */
1204 if (!bfd_mach_o_mangle_symbols (abfd))
1205 return FALSE;
1206
3af9a47b
NC
1207 for (i = 0; i < mdata->header.ncmds; i++)
1208 {
1209 unsigned char buf[8];
1210 bfd_mach_o_load_command *cur = &mdata->commands[i];
1211 unsigned long typeflag;
1212
154a1ee5 1213 typeflag = cur->type | (cur->type_required ? BFD_MACH_O_LC_REQ_DYLD : 0);
3af9a47b
NC
1214
1215 bfd_h_put_32 (abfd, typeflag, buf);
1216 bfd_h_put_32 (abfd, cur->len, buf + 4);
1217
c2f09c75 1218 if (bfd_seek (abfd, cur->offset, SEEK_SET) != 0
91d6fa6a 1219 || bfd_bwrite ((void *) buf, 8, abfd) != 8)
b34976b6 1220 return FALSE;
3af9a47b
NC
1221
1222 switch (cur->type)
1223 {
1224 case BFD_MACH_O_LC_SEGMENT:
ab273af8 1225 if (bfd_mach_o_write_segment_32 (abfd, cur) != 0)
1e8a024a
TG
1226 return FALSE;
1227 break;
1228 case BFD_MACH_O_LC_SEGMENT_64:
ab273af8 1229 if (bfd_mach_o_write_segment_64 (abfd, cur) != 0)
b34976b6 1230 return FALSE;
3af9a47b
NC
1231 break;
1232 case BFD_MACH_O_LC_SYMTAB:
ab273af8 1233 if (!bfd_mach_o_write_symtab (abfd, cur))
b34976b6 1234 return FALSE;
3af9a47b
NC
1235 break;
1236 case BFD_MACH_O_LC_SYMSEG:
1237 break;
1238 case BFD_MACH_O_LC_THREAD:
1239 case BFD_MACH_O_LC_UNIXTHREAD:
ab273af8 1240 if (bfd_mach_o_write_thread (abfd, cur) != 0)
b34976b6 1241 return FALSE;
3af9a47b
NC
1242 break;
1243 case BFD_MACH_O_LC_LOADFVMLIB:
1244 case BFD_MACH_O_LC_IDFVMLIB:
1245 case BFD_MACH_O_LC_IDENT:
1246 case BFD_MACH_O_LC_FVMFILE:
1247 case BFD_MACH_O_LC_PREPAGE:
1248 case BFD_MACH_O_LC_DYSYMTAB:
1249 case BFD_MACH_O_LC_LOAD_DYLIB:
1250 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
1251 case BFD_MACH_O_LC_ID_DYLIB:
046b007d 1252 case BFD_MACH_O_LC_REEXPORT_DYLIB:
3af9a47b
NC
1253 case BFD_MACH_O_LC_LOAD_DYLINKER:
1254 case BFD_MACH_O_LC_ID_DYLINKER:
1255 case BFD_MACH_O_LC_PREBOUND_DYLIB:
1256 case BFD_MACH_O_LC_ROUTINES:
1257 case BFD_MACH_O_LC_SUB_FRAMEWORK:
1258 break;
1259 default:
4a97a0e5
AM
1260 (*_bfd_error_handler) (_("unable to write unknown load command 0x%lx"),
1261 (unsigned long) cur->type);
b34976b6 1262 return FALSE;
3af9a47b
NC
1263 }
1264 }
1265
b34976b6 1266 return TRUE;
3af9a47b
NC
1267}
1268
154a1ee5
TG
1269/* Build Mach-O load commands from the sections. */
1270
1271bfd_boolean
1272bfd_mach_o_build_commands (bfd *abfd)
1273{
046b007d 1274 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
c2f09c75 1275 unsigned int wide = mach_o_wide_p (&mdata->header);
154a1ee5
TG
1276 bfd_mach_o_segment_command *seg;
1277 bfd_mach_o_section *sections;
1278 asection *sec;
c2f09c75
TG
1279 bfd_mach_o_load_command *cmd;
1280 bfd_mach_o_load_command *symtab_cmd;
1281 int target_index;
154a1ee5
TG
1282
1283 /* Return now if commands are already built. */
1284 if (mdata->header.ncmds)
1285 return FALSE;
1286
1287 /* Very simple version: 1 command (segment) containing all sections. */
c2f09c75
TG
1288 mdata->header.ncmds = 2;
1289 mdata->commands = bfd_alloc (abfd, mdata->header.ncmds
154a1ee5
TG
1290 * sizeof (bfd_mach_o_load_command));
1291 if (mdata->commands == NULL)
1292 return FALSE;
c2f09c75
TG
1293 cmd = &mdata->commands[0];
1294 seg = &cmd->command.segment;
1295
154a1ee5
TG
1296 seg->nsects = bfd_count_sections (abfd);
1297 sections = bfd_alloc (abfd, seg->nsects * sizeof (bfd_mach_o_section));
1298 if (sections == NULL)
1299 return FALSE;
1300 seg->sections = sections;
1301
1302 /* Set segment command. */
1303 if (wide)
1304 {
c2f09c75
TG
1305 cmd->type = BFD_MACH_O_LC_SEGMENT_64;
1306 cmd->offset = BFD_MACH_O_HEADER_64_SIZE;
1307 cmd->len = BFD_MACH_O_LC_SEGMENT_64_SIZE
154a1ee5
TG
1308 + BFD_MACH_O_SECTION_64_SIZE * seg->nsects;
1309 }
1310 else
1311 {
c2f09c75
TG
1312 cmd->type = BFD_MACH_O_LC_SEGMENT;
1313 cmd->offset = BFD_MACH_O_HEADER_SIZE;
1314 cmd->len = BFD_MACH_O_LC_SEGMENT_SIZE
154a1ee5
TG
1315 + BFD_MACH_O_SECTION_SIZE * seg->nsects;
1316 }
c2f09c75
TG
1317 cmd->type_required = FALSE;
1318 mdata->header.sizeofcmds = cmd->len;
92bc0e80 1319 mdata->filelen = cmd->offset + cmd->len;
154a1ee5 1320
c2f09c75
TG
1321 /* Set symtab command. */
1322 symtab_cmd = &mdata->commands[1];
1323
1324 symtab_cmd->type = BFD_MACH_O_LC_SYMTAB;
1325 symtab_cmd->offset = cmd->offset + cmd->len;
1326 symtab_cmd->len = 6 * 4;
1327 symtab_cmd->type_required = FALSE;
1328
1329 mdata->header.sizeofcmds += symtab_cmd->len;
92bc0e80 1330 mdata->filelen += symtab_cmd->len;
c2f09c75
TG
1331
1332 /* Fill segment command. */
154a1ee5
TG
1333 memset (seg->segname, 0, sizeof (seg->segname));
1334 seg->vmaddr = 0;
92bc0e80 1335 seg->fileoff = mdata->filelen;
154a1ee5
TG
1336 seg->filesize = 0;
1337 seg->maxprot = BFD_MACH_O_PROT_READ | BFD_MACH_O_PROT_WRITE
1338 | BFD_MACH_O_PROT_EXECUTE;
1339 seg->initprot = seg->maxprot;
1340 seg->flags = 0;
1341
1342 /* Create Mach-O sections. */
c2f09c75 1343 target_index = 0;
154a1ee5
TG
1344 for (sec = abfd->sections; sec; sec = sec->next)
1345 {
1346 sections->bfdsection = sec;
1347 bfd_mach_o_convert_section_name_to_mach_o (abfd, sec, sections);
1348 sections->addr = bfd_get_section_vma (abfd, sec);
1349 sections->size = bfd_get_section_size (sec);
1350 sections->align = bfd_get_section_alignment (abfd, sec);
c2f09c75 1351
92bc0e80
TG
1352 if (sections->size != 0)
1353 {
1354 mdata->filelen = FILE_ALIGN (mdata->filelen, sections->align);
1355 sections->offset = mdata->filelen;
1356 }
1357 else
1358 sections->offset = 0;
154a1ee5
TG
1359 sections->reloff = 0;
1360 sections->nreloc = 0;
1361 sections->reserved1 = 0;
1362 sections->reserved2 = 0;
1363 sections->reserved3 = 0;
1364
92bc0e80 1365 sec->filepos = sections->offset;
c2f09c75 1366 sec->target_index = ++target_index;
154a1ee5 1367
92bc0e80 1368 mdata->filelen += sections->size;
154a1ee5
TG
1369 sections++;
1370 }
92bc0e80 1371 seg->filesize = mdata->filelen - seg->fileoff;
154a1ee5
TG
1372 seg->vmsize = seg->filesize;
1373
1374 return TRUE;
1375}
1376
1377/* Set the contents of a section. */
1378
1379bfd_boolean
1380bfd_mach_o_set_section_contents (bfd *abfd,
1381 asection *section,
1382 const void * location,
1383 file_ptr offset,
1384 bfd_size_type count)
1385{
1386 file_ptr pos;
1387
1388 /* This must be done first, because bfd_set_section_contents is
1389 going to set output_has_begun to TRUE. */
1390 if (! abfd->output_has_begun && ! bfd_mach_o_build_commands (abfd))
1391 return FALSE;
1392
1393 if (count == 0)
1394 return TRUE;
1395
1396 pos = section->filepos + offset;
1397 if (bfd_seek (abfd, pos, SEEK_SET) != 0
1398 || bfd_bwrite (location, count, abfd) != count)
1399 return FALSE;
1400
1401 return TRUE;
1402}
1403
1404int
116c20d2 1405bfd_mach_o_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
a6b96beb 1406 struct bfd_link_info *info ATTRIBUTE_UNUSED)
3af9a47b
NC
1407{
1408 return 0;
1409}
1410
1411/* Make an empty symbol. This is required only because
1412 bfd_make_section_anyway wants to create a symbol for the section. */
1413
154a1ee5 1414asymbol *
116c20d2 1415bfd_mach_o_make_empty_symbol (bfd *abfd)
3af9a47b 1416{
d3ce72d0
NC
1417 asymbol *new_symbol;
1418
1419 new_symbol = bfd_zalloc (abfd, sizeof (bfd_mach_o_asymbol));
1420 if (new_symbol == NULL)
1421 return new_symbol;
1422 new_symbol->the_bfd = abfd;
1423 new_symbol->udata.i = 0;
1424 return new_symbol;
3af9a47b
NC
1425}
1426
154a1ee5 1427static bfd_boolean
116c20d2 1428bfd_mach_o_read_header (bfd *abfd, bfd_mach_o_header *header)
3af9a47b 1429{
1e8a024a
TG
1430 unsigned char buf[32];
1431 unsigned int size;
edeb6e24 1432 bfd_vma (*get32) (const void *) = NULL;
3af9a47b 1433
1e8a024a 1434 /* Just read the magic number. */
c2f09c75 1435 if (bfd_seek (abfd, 0, SEEK_SET) != 0
91d6fa6a 1436 || bfd_bread ((void *) buf, 4, abfd) != 4)
154a1ee5 1437 return FALSE;
3af9a47b 1438
154a1ee5 1439 if (bfd_getb32 (buf) == BFD_MACH_O_MH_MAGIC)
3af9a47b
NC
1440 {
1441 header->byteorder = BFD_ENDIAN_BIG;
154a1ee5 1442 header->magic = BFD_MACH_O_MH_MAGIC;
1e8a024a 1443 header->version = 1;
3af9a47b
NC
1444 get32 = bfd_getb32;
1445 }
154a1ee5 1446 else if (bfd_getl32 (buf) == BFD_MACH_O_MH_MAGIC)
3af9a47b 1447 {
a95a4550 1448 header->byteorder = BFD_ENDIAN_LITTLE;
154a1ee5 1449 header->magic = BFD_MACH_O_MH_MAGIC;
1e8a024a
TG
1450 header->version = 1;
1451 get32 = bfd_getl32;
1452 }
154a1ee5 1453 else if (bfd_getb32 (buf) == BFD_MACH_O_MH_MAGIC_64)
1e8a024a
TG
1454 {
1455 header->byteorder = BFD_ENDIAN_BIG;
154a1ee5 1456 header->magic = BFD_MACH_O_MH_MAGIC_64;
1e8a024a
TG
1457 header->version = 2;
1458 get32 = bfd_getb32;
1459 }
154a1ee5 1460 else if (bfd_getl32 (buf) == BFD_MACH_O_MH_MAGIC_64)
1e8a024a
TG
1461 {
1462 header->byteorder = BFD_ENDIAN_LITTLE;
154a1ee5 1463 header->magic = BFD_MACH_O_MH_MAGIC_64;
1e8a024a 1464 header->version = 2;
3af9a47b
NC
1465 get32 = bfd_getl32;
1466 }
1467 else
1468 {
1469 header->byteorder = BFD_ENDIAN_UNKNOWN;
154a1ee5 1470 return FALSE;
3af9a47b 1471 }
a95a4550 1472
1e8a024a 1473 /* Once the size of the header is known, read the full header. */
c2f09c75 1474 size = mach_o_wide_p (header) ?
154a1ee5 1475 BFD_MACH_O_HEADER_64_SIZE : BFD_MACH_O_HEADER_SIZE;
1e8a024a 1476
c2f09c75 1477 if (bfd_seek (abfd, 0, SEEK_SET) != 0
91d6fa6a 1478 || bfd_bread ((void *) buf, size, abfd) != size)
154a1ee5 1479 return FALSE;
1e8a024a 1480
3af9a47b
NC
1481 header->cputype = (*get32) (buf + 4);
1482 header->cpusubtype = (*get32) (buf + 8);
1483 header->filetype = (*get32) (buf + 12);
1484 header->ncmds = (*get32) (buf + 16);
1485 header->sizeofcmds = (*get32) (buf + 20);
1486 header->flags = (*get32) (buf + 24);
1487
c2f09c75 1488 if (mach_o_wide_p (header))
1e8a024a
TG
1489 header->reserved = (*get32) (buf + 28);
1490
154a1ee5 1491 return TRUE;
3af9a47b
NC
1492}
1493
1494static asection *
15e1c58a
TG
1495bfd_mach_o_make_bfd_section (bfd *abfd, bfd_mach_o_section *section,
1496 unsigned long prot)
3af9a47b
NC
1497{
1498 asection *bfdsec;
1499 char *sname;
117ed4f8 1500 flagword flags;
3af9a47b 1501
8462aec7 1502 bfd_mach_o_convert_section_name_to_bfd (abfd, section, &sname, &flags);
3af9a47b
NC
1503 if (sname == NULL)
1504 return NULL;
3af9a47b 1505
8462aec7 1506 if (flags == SEC_NO_FLAGS)
ef17cb22 1507 {
8462aec7
TG
1508 /* Try to guess flags. */
1509 if (section->flags & BFD_MACH_O_S_ATTR_DEBUG)
1510 flags = SEC_DEBUGGING;
1511 else
1512 {
1513 flags = SEC_ALLOC;
1514 if ((section->flags & BFD_MACH_O_SECTION_TYPE_MASK)
1515 != BFD_MACH_O_S_ZEROFILL)
1516 {
1517 flags |= SEC_LOAD;
1518 if (prot & BFD_MACH_O_PROT_EXECUTE)
1519 flags |= SEC_CODE;
1520 if (prot & BFD_MACH_O_PROT_WRITE)
1521 flags |= SEC_DATA;
1522 else if (prot & BFD_MACH_O_PROT_READ)
1523 flags |= SEC_READONLY;
1524 }
1525 }
ef17cb22 1526 }
15e1c58a
TG
1527 else
1528 {
8462aec7
TG
1529 if ((flags & SEC_DEBUGGING) == 0)
1530 flags |= SEC_ALLOC;
15e1c58a 1531 }
8462aec7
TG
1532
1533 if (section->offset != 0)
1534 flags |= SEC_HAS_CONTENTS;
92bc0e80
TG
1535 if (section->nreloc != 0)
1536 flags |= SEC_RELOC;
1537
117ed4f8 1538 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, flags);
3af9a47b
NC
1539 if (bfdsec == NULL)
1540 return NULL;
a95a4550 1541
3af9a47b
NC
1542 bfdsec->vma = section->addr;
1543 bfdsec->lma = section->addr;
eea6121a 1544 bfdsec->size = section->size;
3af9a47b
NC
1545 bfdsec->filepos = section->offset;
1546 bfdsec->alignment_power = section->align;
1e8a024a 1547 bfdsec->segment_mark = 0;
92bc0e80
TG
1548 bfdsec->reloc_count = section->nreloc;
1549 bfdsec->rel_filepos = section->reloff;
3af9a47b 1550
3af9a47b
NC
1551 return bfdsec;
1552}
1553
1554static int
ab273af8
TG
1555bfd_mach_o_read_section_32 (bfd *abfd,
1556 bfd_mach_o_section *section,
1557 unsigned int offset,
1558 unsigned long prot)
3af9a47b 1559{
154a1ee5 1560 unsigned char buf[BFD_MACH_O_SECTION_SIZE];
3af9a47b 1561
c2f09c75 1562 if (bfd_seek (abfd, offset, SEEK_SET) != 0
91d6fa6a 1563 || (bfd_bread ((void *) buf, BFD_MACH_O_SECTION_SIZE, abfd)
c2f09c75 1564 != BFD_MACH_O_SECTION_SIZE))
3af9a47b 1565 return -1;
a95a4550 1566
3af9a47b
NC
1567 memcpy (section->sectname, buf, 16);
1568 section->sectname[16] = '\0';
1569 memcpy (section->segname, buf + 16, 16);
1570 section->segname[16] = '\0';
1571 section->addr = bfd_h_get_32 (abfd, buf + 32);
1572 section->size = bfd_h_get_32 (abfd, buf + 36);
1573 section->offset = bfd_h_get_32 (abfd, buf + 40);
1574 section->align = bfd_h_get_32 (abfd, buf + 44);
1575 section->reloff = bfd_h_get_32 (abfd, buf + 48);
1576 section->nreloc = bfd_h_get_32 (abfd, buf + 52);
1577 section->flags = bfd_h_get_32 (abfd, buf + 56);
1578 section->reserved1 = bfd_h_get_32 (abfd, buf + 60);
1579 section->reserved2 = bfd_h_get_32 (abfd, buf + 64);
1e8a024a 1580 section->reserved3 = 0;
15e1c58a 1581 section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section, prot);
1e8a024a
TG
1582
1583 if (section->bfdsection == NULL)
1584 return -1;
1585
1586 return 0;
1587}
1588
1589static int
ab273af8
TG
1590bfd_mach_o_read_section_64 (bfd *abfd,
1591 bfd_mach_o_section *section,
1592 unsigned int offset,
1593 unsigned long prot)
1e8a024a 1594{
154a1ee5 1595 unsigned char buf[BFD_MACH_O_SECTION_64_SIZE];
1e8a024a 1596
c2f09c75 1597 if (bfd_seek (abfd, offset, SEEK_SET) != 0
91d6fa6a 1598 || (bfd_bread ((void *) buf, BFD_MACH_O_SECTION_64_SIZE, abfd)
c2f09c75 1599 != BFD_MACH_O_SECTION_64_SIZE))
1e8a024a
TG
1600 return -1;
1601
1602 memcpy (section->sectname, buf, 16);
1603 section->sectname[16] = '\0';
1604 memcpy (section->segname, buf + 16, 16);
1605 section->segname[16] = '\0';
1606 section->addr = bfd_h_get_64 (abfd, buf + 32);
1607 section->size = bfd_h_get_64 (abfd, buf + 40);
1608 section->offset = bfd_h_get_32 (abfd, buf + 48);
1609 section->align = bfd_h_get_32 (abfd, buf + 52);
1610 section->reloff = bfd_h_get_32 (abfd, buf + 56);
1611 section->nreloc = bfd_h_get_32 (abfd, buf + 60);
1612 section->flags = bfd_h_get_32 (abfd, buf + 64);
1613 section->reserved1 = bfd_h_get_32 (abfd, buf + 68);
1614 section->reserved2 = bfd_h_get_32 (abfd, buf + 72);
1615 section->reserved3 = bfd_h_get_32 (abfd, buf + 76);
15e1c58a 1616 section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section, prot);
3af9a47b
NC
1617
1618 if (section->bfdsection == NULL)
1619 return -1;
1620
1621 return 0;
1622}
1623
1e8a024a 1624static int
ab273af8
TG
1625bfd_mach_o_read_section (bfd *abfd,
1626 bfd_mach_o_section *section,
1627 unsigned int offset,
1628 unsigned long prot,
1629 unsigned int wide)
1e8a024a
TG
1630{
1631 if (wide)
ab273af8 1632 return bfd_mach_o_read_section_64 (abfd, section, offset, prot);
1e8a024a 1633 else
ab273af8 1634 return bfd_mach_o_read_section_32 (abfd, section, offset, prot);
1e8a024a
TG
1635}
1636
046b007d 1637static int
ab273af8
TG
1638bfd_mach_o_read_symtab_symbol (bfd *abfd,
1639 bfd_mach_o_symtab_command *sym,
1640 bfd_mach_o_asymbol *s,
1641 unsigned long i)
3af9a47b 1642{
046b007d 1643 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
c2f09c75 1644 unsigned int wide = mach_o_wide_p (&mdata->header);
046b007d
TG
1645 unsigned int symwidth =
1646 wide ? BFD_MACH_O_NLIST_64_SIZE : BFD_MACH_O_NLIST_SIZE;
92bc0e80 1647 unsigned int symoff = sym->symoff + (i * symwidth);
1e8a024a 1648 unsigned char buf[16];
3af9a47b
NC
1649 unsigned char type = -1;
1650 unsigned char section = -1;
1651 short desc = -1;
1e8a024a 1652 symvalue value = -1;
3af9a47b
NC
1653 unsigned long stroff = -1;
1654 unsigned int symtype = -1;
1655
1656 BFD_ASSERT (sym->strtab != NULL);
1657
c2f09c75 1658 if (bfd_seek (abfd, symoff, SEEK_SET) != 0
91d6fa6a 1659 || bfd_bread ((void *) buf, symwidth, abfd) != symwidth)
3af9a47b 1660 {
4a97a0e5
AM
1661 (*_bfd_error_handler) (_("bfd_mach_o_read_symtab_symbol: unable to read %d bytes at %lu"),
1662 symwidth, (unsigned long) symoff);
3af9a47b
NC
1663 return -1;
1664 }
1665
1666 stroff = bfd_h_get_32 (abfd, buf);
1667 type = bfd_h_get_8 (abfd, buf + 4);
c2f09c75 1668 symtype = type & BFD_MACH_O_N_TYPE;
15e1c58a 1669 section = bfd_h_get_8 (abfd, buf + 5);
3af9a47b 1670 desc = bfd_h_get_16 (abfd, buf + 6);
1e8a024a
TG
1671 if (wide)
1672 value = bfd_h_get_64 (abfd, buf + 8);
1673 else
1674 value = bfd_h_get_32 (abfd, buf + 8);
3af9a47b
NC
1675
1676 if (stroff >= sym->strsize)
1677 {
4a97a0e5
AM
1678 (*_bfd_error_handler) (_("bfd_mach_o_read_symtab_symbol: symbol name out of range (%lu >= %lu)"),
1679 (unsigned long) stroff,
1680 (unsigned long) sym->strsize);
a95a4550 1681 return -1;
3af9a47b
NC
1682 }
1683
92bc0e80
TG
1684 s->symbol.the_bfd = abfd;
1685 s->symbol.name = sym->strtab + stroff;
1686 s->symbol.value = value;
1687 s->symbol.flags = 0x0;
1688 s->symbol.udata.i = 0;
1689 s->n_type = type;
1690 s->n_sect = section;
1691 s->n_desc = desc;
3af9a47b
NC
1692
1693 if (type & BFD_MACH_O_N_STAB)
1694 {
92bc0e80
TG
1695 s->symbol.flags |= BSF_DEBUGGING;
1696 s->symbol.section = bfd_und_section_ptr;
15e1c58a
TG
1697 switch (type)
1698 {
1699 case N_FUN:
1700 case N_STSYM:
1701 case N_LCSYM:
1702 case N_BNSYM:
1703 case N_SLINE:
1704 case N_ENSYM:
1705 case N_ECOMM:
1706 case N_ECOML:
1707 case N_GSYM:
1708 if ((section > 0) && (section <= mdata->nsects))
1709 {
92bc0e80
TG
1710 s->symbol.section = mdata->sections[section - 1]->bfdsection;
1711 s->symbol.value =
1712 s->symbol.value - mdata->sections[section - 1]->addr;
15e1c58a
TG
1713 }
1714 break;
1715 }
3af9a47b
NC
1716 }
1717 else
1718 {
1719 if (type & BFD_MACH_O_N_PEXT)
92bc0e80 1720 s->symbol.flags |= BSF_GLOBAL;
c2f09c75 1721
3af9a47b 1722 if (type & BFD_MACH_O_N_EXT)
92bc0e80 1723 s->symbol.flags |= BSF_GLOBAL;
15e1c58a
TG
1724
1725 if (!(type & (BFD_MACH_O_N_PEXT | BFD_MACH_O_N_EXT)))
92bc0e80 1726 s->symbol.flags |= BSF_LOCAL;
3af9a47b
NC
1727
1728 switch (symtype)
1729 {
1730 case BFD_MACH_O_N_UNDF:
c2f09c75 1731 if (type == (BFD_MACH_O_N_UNDF | BFD_MACH_O_N_EXT)
92bc0e80 1732 && s->symbol.value != 0)
c2f09c75
TG
1733 {
1734 /* A common symbol. */
92bc0e80
TG
1735 s->symbol.section = bfd_com_section_ptr;
1736 s->symbol.flags = BSF_NO_FLAGS;
c2f09c75
TG
1737 }
1738 else
92bc0e80
TG
1739 {
1740 s->symbol.section = bfd_und_section_ptr;
1741 if (s->n_desc & BFD_MACH_O_N_WEAK_REF)
1742 s->symbol.flags |= BSF_WEAK;
1743 }
3af9a47b
NC
1744 break;
1745 case BFD_MACH_O_N_PBUD:
92bc0e80 1746 s->symbol.section = bfd_und_section_ptr;
3af9a47b
NC
1747 break;
1748 case BFD_MACH_O_N_ABS:
92bc0e80 1749 s->symbol.section = bfd_abs_section_ptr;
3af9a47b
NC
1750 break;
1751 case BFD_MACH_O_N_SECT:
1752 if ((section > 0) && (section <= mdata->nsects))
1753 {
92bc0e80
TG
1754 s->symbol.section = mdata->sections[section - 1]->bfdsection;
1755 s->symbol.value =
1756 s->symbol.value - mdata->sections[section - 1]->addr;
3af9a47b
NC
1757 }
1758 else
1759 {
1760 /* Mach-O uses 0 to mean "no section"; not an error. */
1761 if (section != 0)
1762 {
4a97a0e5
AM
1763 (*_bfd_error_handler) (_("bfd_mach_o_read_symtab_symbol: "
1764 "symbol \"%s\" specified invalid section %d (max %lu): setting to undefined"),
1765 s->symbol.name, section, mdata->nsects);
3af9a47b 1766 }
92bc0e80 1767 s->symbol.section = bfd_und_section_ptr;
3af9a47b
NC
1768 }
1769 break;
1770 case BFD_MACH_O_N_INDR:
4a97a0e5
AM
1771 (*_bfd_error_handler) (_("bfd_mach_o_read_symtab_symbol: "
1772 "symbol \"%s\" is unsupported 'indirect' reference: setting to undefined"),
1773 s->symbol.name);
92bc0e80 1774 s->symbol.section = bfd_und_section_ptr;
3af9a47b
NC
1775 break;
1776 default:
4a97a0e5
AM
1777 (*_bfd_error_handler) (_("bfd_mach_o_read_symtab_symbol: "
1778 "symbol \"%s\" specified invalid type field 0x%x: setting to undefined"),
1779 s->symbol.name, symtype);
92bc0e80 1780 s->symbol.section = bfd_und_section_ptr;
3af9a47b
NC
1781 break;
1782 }
1783 }
1784
1785 return 0;
1786}
1787
046b007d 1788static int
ab273af8 1789bfd_mach_o_read_symtab_strtab (bfd *abfd)
3af9a47b 1790{
046b007d
TG
1791 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
1792 bfd_mach_o_symtab_command *sym = mdata->symtab;
1793
1794 /* Fail if there is no symtab. */
1795 if (sym == NULL)
1796 return -1;
1797
1798 /* Success if already loaded. */
1799 if (sym->strtab)
1800 return 0;
3af9a47b
NC
1801
1802 if (abfd->flags & BFD_IN_MEMORY)
1803 {
1804 struct bfd_in_memory *b;
1805
1806 b = (struct bfd_in_memory *) abfd->iostream;
1807
1808 if ((sym->stroff + sym->strsize) > b->size)
1809 {
1810 bfd_set_error (bfd_error_file_truncated);
1811 return -1;
1812 }
f075ee0c 1813 sym->strtab = (char *) b->buffer + sym->stroff;
3af9a47b 1814 }
046b007d 1815 else
3af9a47b 1816 {
046b007d
TG
1817 sym->strtab = bfd_alloc (abfd, sym->strsize);
1818 if (sym->strtab == NULL)
1819 return -1;
1820
1821 if (bfd_seek (abfd, sym->stroff, SEEK_SET) != 0
91d6fa6a 1822 || bfd_bread ((void *) sym->strtab, sym->strsize, abfd) != sym->strsize)
046b007d
TG
1823 {
1824 bfd_set_error (bfd_error_file_truncated);
1825 return -1;
1826 }
3af9a47b
NC
1827 }
1828
1829 return 0;
1830}
1831
046b007d 1832static int
ab273af8 1833bfd_mach_o_read_symtab_symbols (bfd *abfd)
3af9a47b 1834{
046b007d
TG
1835 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
1836 bfd_mach_o_symtab_command *sym = mdata->symtab;
3af9a47b
NC
1837 unsigned long i;
1838 int ret;
1839
092d27ff
TG
1840 if (sym == NULL || sym->symbols)
1841 {
1842 /* Return now if there are no symbols or if already loaded. */
1843 return 0;
1844 }
046b007d 1845
92bc0e80 1846 sym->symbols = bfd_alloc (abfd, sym->nsyms * sizeof (bfd_mach_o_asymbol));
3af9a47b
NC
1847
1848 if (sym->symbols == NULL)
1849 {
4a97a0e5 1850 (*_bfd_error_handler) (_("bfd_mach_o_read_symtab_symbols: unable to allocate memory for symbols"));
a95a4550 1851 return -1;
3af9a47b 1852 }
a95a4550 1853
ab273af8 1854 ret = bfd_mach_o_read_symtab_strtab (abfd);
3af9a47b
NC
1855 if (ret != 0)
1856 return ret;
1857
1858 for (i = 0; i < sym->nsyms; i++)
1859 {
ab273af8 1860 ret = bfd_mach_o_read_symtab_symbol (abfd, sym, &sym->symbols[i], i);
3af9a47b
NC
1861 if (ret != 0)
1862 return ret;
1863 }
a95a4550 1864
3af9a47b
NC
1865 return 0;
1866}
1867
1868int
ab273af8
TG
1869bfd_mach_o_read_dysymtab_symbol (bfd *abfd,
1870 bfd_mach_o_dysymtab_command *dysym,
1871 bfd_mach_o_symtab_command *sym,
1872 bfd_mach_o_asymbol *s,
1873 unsigned long i)
3af9a47b
NC
1874{
1875 unsigned long isymoff = dysym->indirectsymoff + (i * 4);
91d6fa6a 1876 unsigned long sym_index;
3af9a47b
NC
1877 unsigned char buf[4];
1878
1879 BFD_ASSERT (i < dysym->nindirectsyms);
a95a4550 1880
c2f09c75 1881 if (bfd_seek (abfd, isymoff, SEEK_SET) != 0
91d6fa6a 1882 || bfd_bread ((void *) buf, 4, abfd) != 4)
3af9a47b 1883 {
4a97a0e5
AM
1884 (*_bfd_error_handler) (_("bfd_mach_o_read_dysymtab_symbol: unable to read %lu bytes at %lu"),
1885 (unsigned long) 4, isymoff);
3af9a47b
NC
1886 return -1;
1887 }
91d6fa6a 1888 sym_index = bfd_h_get_32 (abfd, buf);
a95a4550 1889
91d6fa6a 1890 return bfd_mach_o_read_symtab_symbol (abfd, sym, s, sym_index);
3af9a47b
NC
1891}
1892
1893static const char *
116c20d2 1894bfd_mach_o_i386_flavour_string (unsigned int flavour)
3af9a47b
NC
1895{
1896 switch ((int) flavour)
1897 {
15e1c58a
TG
1898 case BFD_MACH_O_x86_THREAD_STATE32: return "x86_THREAD_STATE32";
1899 case BFD_MACH_O_x86_FLOAT_STATE32: return "x86_FLOAT_STATE32";
1900 case BFD_MACH_O_x86_EXCEPTION_STATE32: return "x86_EXCEPTION_STATE32";
1901 case BFD_MACH_O_x86_THREAD_STATE64: return "x86_THREAD_STATE64";
1902 case BFD_MACH_O_x86_FLOAT_STATE64: return "x86_FLOAT_STATE64";
1903 case BFD_MACH_O_x86_EXCEPTION_STATE64: return "x86_EXCEPTION_STATE64";
1904 case BFD_MACH_O_x86_THREAD_STATE: return "x86_THREAD_STATE";
1905 case BFD_MACH_O_x86_FLOAT_STATE: return "x86_FLOAT_STATE";
1906 case BFD_MACH_O_x86_EXCEPTION_STATE: return "x86_EXCEPTION_STATE";
1907 case BFD_MACH_O_x86_DEBUG_STATE32: return "x86_DEBUG_STATE32";
1908 case BFD_MACH_O_x86_DEBUG_STATE64: return "x86_DEBUG_STATE64";
1909 case BFD_MACH_O_x86_DEBUG_STATE: return "x86_DEBUG_STATE";
b32e07d7 1910 case BFD_MACH_O_x86_THREAD_STATE_NONE: return "x86_THREAD_STATE_NONE";
3af9a47b
NC
1911 default: return "UNKNOWN";
1912 }
1913}
1914
1915static const char *
116c20d2 1916bfd_mach_o_ppc_flavour_string (unsigned int flavour)
3af9a47b
NC
1917{
1918 switch ((int) flavour)
1919 {
b32e07d7
TG
1920 case BFD_MACH_O_PPC_THREAD_STATE: return "PPC_THREAD_STATE";
1921 case BFD_MACH_O_PPC_FLOAT_STATE: return "PPC_FLOAT_STATE";
1922 case BFD_MACH_O_PPC_EXCEPTION_STATE: return "PPC_EXCEPTION_STATE";
1923 case BFD_MACH_O_PPC_VECTOR_STATE: return "PPC_VECTOR_STATE";
1924 case BFD_MACH_O_PPC_THREAD_STATE64: return "PPC_THREAD_STATE64";
1925 case BFD_MACH_O_PPC_EXCEPTION_STATE64: return "PPC_EXCEPTION_STATE64";
3af9a47b
NC
1926 default: return "UNKNOWN";
1927 }
1928}
1929
1930static int
ab273af8 1931bfd_mach_o_read_dylinker (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1932{
1933 bfd_mach_o_dylinker_command *cmd = &command->command.dylinker;
1934 unsigned char buf[4];
1935 unsigned int nameoff;
3af9a47b
NC
1936
1937 BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLINKER)
1938 || (command->type == BFD_MACH_O_LC_LOAD_DYLINKER));
1939
c2f09c75 1940 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 1941 || bfd_bread ((void *) buf, 4, abfd) != 4)
3af9a47b
NC
1942 return -1;
1943
1944 nameoff = bfd_h_get_32 (abfd, buf + 0);
1945
1946 cmd->name_offset = command->offset + nameoff;
1947 cmd->name_len = command->len - nameoff;
b32e07d7
TG
1948 cmd->name_str = bfd_alloc (abfd, cmd->name_len);
1949 if (cmd->name_str == NULL)
3af9a47b 1950 return -1;
b32e07d7
TG
1951 if (bfd_seek (abfd, cmd->name_offset, SEEK_SET) != 0
1952 || bfd_bread (cmd->name_str, cmd->name_len, abfd) != cmd->name_len)
3af9a47b 1953 return -1;
3af9a47b
NC
1954 return 0;
1955}
1956
1957static int
ab273af8 1958bfd_mach_o_read_dylib (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1959{
1960 bfd_mach_o_dylib_command *cmd = &command->command.dylib;
1961 unsigned char buf[16];
1962 unsigned int nameoff;
3af9a47b 1963
046b007d
TG
1964 switch (command->type)
1965 {
1966 case BFD_MACH_O_LC_LOAD_DYLIB:
046b007d 1967 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
046b007d 1968 case BFD_MACH_O_LC_ID_DYLIB:
046b007d 1969 case BFD_MACH_O_LC_REEXPORT_DYLIB:
046b007d
TG
1970 break;
1971 default:
b32e07d7
TG
1972 BFD_FAIL ();
1973 return -1;
046b007d 1974 }
3af9a47b 1975
c2f09c75 1976 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 1977 || bfd_bread ((void *) buf, 16, abfd) != 16)
3af9a47b
NC
1978 return -1;
1979
1980 nameoff = bfd_h_get_32 (abfd, buf + 0);
1981 cmd->timestamp = bfd_h_get_32 (abfd, buf + 4);
1982 cmd->current_version = bfd_h_get_32 (abfd, buf + 8);
1983 cmd->compatibility_version = bfd_h_get_32 (abfd, buf + 12);
1984
1985 cmd->name_offset = command->offset + nameoff;
1986 cmd->name_len = command->len - nameoff;
b32e07d7
TG
1987 cmd->name_str = bfd_alloc (abfd, cmd->name_len);
1988 if (cmd->name_str == NULL)
3af9a47b 1989 return -1;
b32e07d7
TG
1990 if (bfd_seek (abfd, cmd->name_offset, SEEK_SET) != 0
1991 || bfd_bread (cmd->name_str, cmd->name_len, abfd) != cmd->name_len)
3af9a47b 1992 return -1;
3af9a47b
NC
1993 return 0;
1994}
1995
1996static int
ab273af8
TG
1997bfd_mach_o_read_prebound_dylib (bfd *abfd ATTRIBUTE_UNUSED,
1998 bfd_mach_o_load_command *command ATTRIBUTE_UNUSED)
3af9a47b
NC
1999{
2000 /* bfd_mach_o_prebound_dylib_command *cmd = &command->command.prebound_dylib; */
2001
2002 BFD_ASSERT (command->type == BFD_MACH_O_LC_PREBOUND_DYLIB);
2003 return 0;
2004}
2005
2006static int
ab273af8 2007bfd_mach_o_read_thread (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b 2008{
b32e07d7 2009 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b
NC
2010 bfd_mach_o_thread_command *cmd = &command->command.thread;
2011 unsigned char buf[8];
92bc0e80 2012 unsigned int offset;
3af9a47b
NC
2013 unsigned int nflavours;
2014 unsigned int i;
2015
2016 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
2017 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
2018
b32e07d7 2019 /* Count the number of threads. */
3af9a47b
NC
2020 offset = 8;
2021 nflavours = 0;
2022 while (offset != command->len)
2023 {
2024 if (offset >= command->len)
2025 return -1;
2026
c2f09c75 2027 if (bfd_seek (abfd, command->offset + offset, SEEK_SET) != 0
91d6fa6a 2028 || bfd_bread ((void *) buf, 8, abfd) != 8)
3af9a47b
NC
2029 return -1;
2030
2031 offset += 8 + bfd_h_get_32 (abfd, buf + 4) * 4;
2032 nflavours++;
2033 }
2034
b32e07d7
TG
2035 /* Allocate threads. */
2036 cmd->flavours = bfd_alloc
2037 (abfd, nflavours * sizeof (bfd_mach_o_thread_flavour));
3af9a47b
NC
2038 if (cmd->flavours == NULL)
2039 return -1;
2040 cmd->nflavours = nflavours;
2041
2042 offset = 8;
2043 nflavours = 0;
2044 while (offset != command->len)
2045 {
2046 if (offset >= command->len)
2047 return -1;
2048
2049 if (nflavours >= cmd->nflavours)
2050 return -1;
2051
c2f09c75 2052 if (bfd_seek (abfd, command->offset + offset, SEEK_SET) != 0
91d6fa6a 2053 || bfd_bread ((void *) buf, 8, abfd) != 8)
3af9a47b
NC
2054 return -1;
2055
2056 cmd->flavours[nflavours].flavour = bfd_h_get_32 (abfd, buf);
2057 cmd->flavours[nflavours].offset = command->offset + offset + 8;
2058 cmd->flavours[nflavours].size = bfd_h_get_32 (abfd, buf + 4) * 4;
2059 offset += cmd->flavours[nflavours].size + 8;
2060 nflavours++;
2061 }
2062
2063 for (i = 0; i < nflavours; i++)
2064 {
2065 asection *bfdsec;
2066 unsigned int snamelen;
2067 char *sname;
2068 const char *flavourstr;
2069 const char *prefix = "LC_THREAD";
a95a4550
AM
2070 unsigned int j = 0;
2071
3af9a47b
NC
2072 switch (mdata->header.cputype)
2073 {
2074 case BFD_MACH_O_CPU_TYPE_POWERPC:
1e8a024a 2075 case BFD_MACH_O_CPU_TYPE_POWERPC_64:
3af9a47b
NC
2076 flavourstr = bfd_mach_o_ppc_flavour_string (cmd->flavours[i].flavour);
2077 break;
2078 case BFD_MACH_O_CPU_TYPE_I386:
1e8a024a 2079 case BFD_MACH_O_CPU_TYPE_X86_64:
3af9a47b
NC
2080 flavourstr = bfd_mach_o_i386_flavour_string (cmd->flavours[i].flavour);
2081 break;
2082 default:
2083 flavourstr = "UNKNOWN_ARCHITECTURE";
2084 break;
2085 }
a95a4550 2086
3af9a47b 2087 snamelen = strlen (prefix) + 1 + 20 + 1 + strlen (flavourstr) + 1;
116c20d2 2088 sname = bfd_alloc (abfd, snamelen);
3af9a47b
NC
2089 if (sname == NULL)
2090 return -1;
2091
2092 for (;;)
2093 {
a95a4550
AM
2094 sprintf (sname, "%s.%s.%u", prefix, flavourstr, j);
2095 if (bfd_get_section_by_name (abfd, sname) == NULL)
3af9a47b 2096 break;
a95a4550 2097 j++;
3af9a47b
NC
2098 }
2099
117ed4f8 2100 bfdsec = bfd_make_section_with_flags (abfd, sname, SEC_HAS_CONTENTS);
a95a4550 2101
3af9a47b
NC
2102 bfdsec->vma = 0;
2103 bfdsec->lma = 0;
eea6121a 2104 bfdsec->size = cmd->flavours[i].size;
3af9a47b
NC
2105 bfdsec->filepos = cmd->flavours[i].offset;
2106 bfdsec->alignment_power = 0x0;
3af9a47b
NC
2107
2108 cmd->section = bfdsec;
2109 }
2110
2111 return 0;
2112}
2113
a95a4550 2114static int
ab273af8 2115bfd_mach_o_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b 2116{
046b007d 2117 bfd_mach_o_dysymtab_command *cmd = &command->command.dysymtab;
b32e07d7 2118 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b
NC
2119 unsigned char buf[72];
2120
2121 BFD_ASSERT (command->type == BFD_MACH_O_LC_DYSYMTAB);
2122
c2f09c75 2123 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 2124 || bfd_bread ((void *) buf, 72, abfd) != 72)
3af9a47b
NC
2125 return -1;
2126
046b007d
TG
2127 cmd->ilocalsym = bfd_h_get_32 (abfd, buf + 0);
2128 cmd->nlocalsym = bfd_h_get_32 (abfd, buf + 4);
2129 cmd->iextdefsym = bfd_h_get_32 (abfd, buf + 8);
2130 cmd->nextdefsym = bfd_h_get_32 (abfd, buf + 12);
2131 cmd->iundefsym = bfd_h_get_32 (abfd, buf + 16);
2132 cmd->nundefsym = bfd_h_get_32 (abfd, buf + 20);
2133 cmd->tocoff = bfd_h_get_32 (abfd, buf + 24);
2134 cmd->ntoc = bfd_h_get_32 (abfd, buf + 28);
2135 cmd->modtaboff = bfd_h_get_32 (abfd, buf + 32);
2136 cmd->nmodtab = bfd_h_get_32 (abfd, buf + 36);
2137 cmd->extrefsymoff = bfd_h_get_32 (abfd, buf + 40);
2138 cmd->nextrefsyms = bfd_h_get_32 (abfd, buf + 44);
2139 cmd->indirectsymoff = bfd_h_get_32 (abfd, buf + 48);
2140 cmd->nindirectsyms = bfd_h_get_32 (abfd, buf + 52);
2141 cmd->extreloff = bfd_h_get_32 (abfd, buf + 56);
2142 cmd->nextrel = bfd_h_get_32 (abfd, buf + 60);
2143 cmd->locreloff = bfd_h_get_32 (abfd, buf + 64);
2144 cmd->nlocrel = bfd_h_get_32 (abfd, buf + 68);
2145
2146 if (cmd->nmodtab != 0)
2147 {
046b007d
TG
2148 unsigned int i;
2149 int wide = bfd_mach_o_wide_p (abfd);
2150 unsigned int module_len = wide ? 56 : 52;
2151
2152 cmd->dylib_module =
2153 bfd_alloc (abfd, cmd->nmodtab * sizeof (bfd_mach_o_dylib_module));
2154 if (cmd->dylib_module == NULL)
2155 return -1;
2156
2157 if (bfd_seek (abfd, cmd->modtaboff, SEEK_SET) != 0)
2158 return -1;
2159
2160 for (i = 0; i < cmd->nmodtab; i++)
2161 {
2162 bfd_mach_o_dylib_module *module = &cmd->dylib_module[i];
2163 unsigned long v;
2164
91d6fa6a 2165 if (bfd_bread ((void *) buf, module_len, abfd) != module_len)
046b007d
TG
2166 return -1;
2167
2168 module->module_name_idx = bfd_h_get_32 (abfd, buf + 0);
2169 module->iextdefsym = bfd_h_get_32 (abfd, buf + 4);
2170 module->nextdefsym = bfd_h_get_32 (abfd, buf + 8);
2171 module->irefsym = bfd_h_get_32 (abfd, buf + 12);
2172 module->nrefsym = bfd_h_get_32 (abfd, buf + 16);
2173 module->ilocalsym = bfd_h_get_32 (abfd, buf + 20);
2174 module->nlocalsym = bfd_h_get_32 (abfd, buf + 24);
2175 module->iextrel = bfd_h_get_32 (abfd, buf + 28);
2176 module->nextrel = bfd_h_get_32 (abfd, buf + 32);
2177 v = bfd_h_get_32 (abfd, buf +36);
2178 module->iinit = v & 0xffff;
2179 module->iterm = (v >> 16) & 0xffff;
2180 v = bfd_h_get_32 (abfd, buf + 40);
2181 module->ninit = v & 0xffff;
2182 module->nterm = (v >> 16) & 0xffff;
2183 if (wide)
2184 {
2185 module->objc_module_info_size = bfd_h_get_32 (abfd, buf + 44);
2186 module->objc_module_info_addr = bfd_h_get_64 (abfd, buf + 48);
2187 }
2188 else
2189 {
2190 module->objc_module_info_addr = bfd_h_get_32 (abfd, buf + 44);
2191 module->objc_module_info_size = bfd_h_get_32 (abfd, buf + 48);
2192 }
2193 }
2194 }
2195
2196 if (cmd->ntoc != 0)
2197 {
046b007d
TG
2198 unsigned int i;
2199
2200 cmd->dylib_toc = bfd_alloc
2201 (abfd, cmd->ntoc * sizeof (bfd_mach_o_dylib_table_of_content));
2202 if (cmd->dylib_toc == NULL)
2203 return -1;
2204
2205 if (bfd_seek (abfd, cmd->tocoff, SEEK_SET) != 0)
2206 return -1;
2207
2208 for (i = 0; i < cmd->ntoc; i++)
2209 {
2210 bfd_mach_o_dylib_table_of_content *toc = &cmd->dylib_toc[i];
2211
91d6fa6a 2212 if (bfd_bread ((void *) buf, 8, abfd) != 8)
046b007d
TG
2213 return -1;
2214
2215 toc->symbol_index = bfd_h_get_32 (abfd, buf + 0);
2216 toc->module_index = bfd_h_get_32 (abfd, buf + 4);
2217 }
2218 }
2219
2220 if (cmd->nindirectsyms != 0)
2221 {
046b007d
TG
2222 unsigned int i;
2223
2224 cmd->indirect_syms = bfd_alloc
2225 (abfd, cmd->nindirectsyms * sizeof (unsigned int));
2226 if (cmd->indirect_syms == NULL)
2227 return -1;
2228
2229 if (bfd_seek (abfd, cmd->indirectsymoff, SEEK_SET) != 0)
2230 return -1;
2231
2232 for (i = 0; i < cmd->nindirectsyms; i++)
2233 {
2234 unsigned int *is = &cmd->indirect_syms[i];
2235
91d6fa6a 2236 if (bfd_bread ((void *) buf, 4, abfd) != 4)
046b007d
TG
2237 return -1;
2238
2239 *is = bfd_h_get_32 (abfd, buf + 0);
2240 }
2241 }
2242
2243 if (cmd->nextrefsyms != 0)
2244 {
046b007d
TG
2245 unsigned long v;
2246 unsigned int i;
2247
2248 cmd->ext_refs = bfd_alloc
2249 (abfd, cmd->nextrefsyms * sizeof (bfd_mach_o_dylib_reference));
2250 if (cmd->ext_refs == NULL)
2251 return -1;
2252
2253 if (bfd_seek (abfd, cmd->extrefsymoff, SEEK_SET) != 0)
2254 return -1;
2255
2256 for (i = 0; i < cmd->nextrefsyms; i++)
2257 {
2258 bfd_mach_o_dylib_reference *ref = &cmd->ext_refs[i];
2259
91d6fa6a 2260 if (bfd_bread ((void *) buf, 4, abfd) != 4)
046b007d
TG
2261 return -1;
2262
b32e07d7
TG
2263 /* Fields isym and flags are written as bit-fields, thus we need
2264 a specific processing for endianness. */
046b007d 2265 v = bfd_h_get_32 (abfd, buf + 0);
b32e07d7
TG
2266 if (bfd_big_endian (abfd))
2267 {
2268 ref->isym = (v >> 8) & 0xffffff;
2269 ref->flags = v & 0xff;
2270 }
2271 else
2272 {
2273 ref->isym = v & 0xffffff;
2274 ref->flags = (v >> 24) & 0xff;
2275 }
046b007d
TG
2276 }
2277 }
3af9a47b 2278
b32e07d7
TG
2279 if (mdata->dysymtab)
2280 return -1;
2281 mdata->dysymtab = cmd;
2282
3af9a47b
NC
2283 return 0;
2284}
2285
a95a4550 2286static int
ab273af8 2287bfd_mach_o_read_symtab (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b 2288{
046b007d
TG
2289 bfd_mach_o_symtab_command *symtab = &command->command.symtab;
2290 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b 2291 unsigned char buf[16];
3af9a47b
NC
2292
2293 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
2294
c2f09c75 2295 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 2296 || bfd_bread ((void *) buf, 16, abfd) != 16)
3af9a47b 2297 return -1;
a95a4550 2298
046b007d
TG
2299 symtab->symoff = bfd_h_get_32 (abfd, buf);
2300 symtab->nsyms = bfd_h_get_32 (abfd, buf + 4);
2301 symtab->stroff = bfd_h_get_32 (abfd, buf + 8);
2302 symtab->strsize = bfd_h_get_32 (abfd, buf + 12);
2303 symtab->symbols = NULL;
2304 symtab->strtab = NULL;
3af9a47b 2305
046b007d 2306 if (symtab->nsyms != 0)
15e1c58a
TG
2307 abfd->flags |= HAS_SYMS;
2308
046b007d
TG
2309 if (mdata->symtab)
2310 return -1;
2311 mdata->symtab = symtab;
3af9a47b
NC
2312 return 0;
2313}
2314
15e1c58a 2315static int
ab273af8 2316bfd_mach_o_read_uuid (bfd *abfd, bfd_mach_o_load_command *command)
15e1c58a
TG
2317{
2318 bfd_mach_o_uuid_command *cmd = &command->command.uuid;
15e1c58a
TG
2319
2320 BFD_ASSERT (command->type == BFD_MACH_O_LC_UUID);
2321
c2f09c75 2322 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 2323 || bfd_bread ((void *) cmd->uuid, 16, abfd) != 16)
15e1c58a
TG
2324 return -1;
2325
15e1c58a
TG
2326 return 0;
2327}
2328
046b007d 2329static int
ab273af8 2330bfd_mach_o_read_linkedit (bfd *abfd, bfd_mach_o_load_command *command)
046b007d
TG
2331{
2332 bfd_mach_o_linkedit_command *cmd = &command->command.linkedit;
2333 char buf[8];
2334
2335 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 2336 || bfd_bread ((void *) buf, 8, abfd) != 8)
046b007d
TG
2337 return -1;
2338
2339 cmd->dataoff = bfd_get_32 (abfd, buf + 0);
2340 cmd->datasize = bfd_get_32 (abfd, buf + 4);
2341 return 0;
2342}
2343
2344static int
ab273af8 2345bfd_mach_o_read_str (bfd *abfd, bfd_mach_o_load_command *command)
046b007d
TG
2346{
2347 bfd_mach_o_str_command *cmd = &command->command.str;
ad86f1fb 2348 char buf[4];
046b007d
TG
2349 unsigned long off;
2350
2351 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 2352 || bfd_bread ((void *) buf, 4, abfd) != 4)
046b007d
TG
2353 return -1;
2354
2355 off = bfd_get_32 (abfd, buf + 0);
2356 cmd->stroff = command->offset + off;
2357 cmd->str_len = command->len - off;
2358 cmd->str = bfd_alloc (abfd, cmd->str_len);
2359 if (cmd->str == NULL)
2360 return -1;
2361 if (bfd_seek (abfd, cmd->stroff, SEEK_SET) != 0
91d6fa6a 2362 || bfd_bread ((void *) cmd->str, cmd->str_len, abfd) != cmd->str_len)
046b007d
TG
2363 return -1;
2364 return 0;
2365}
2366
ad86f1fb 2367static int
ab273af8 2368bfd_mach_o_read_dyld_info (bfd *abfd, bfd_mach_o_load_command *command)
ad86f1fb
TG
2369{
2370 bfd_mach_o_dyld_info_command *cmd = &command->command.dyld_info;
2371 char buf[40];
2372
2373 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 2374 || bfd_bread ((void *) buf, sizeof (buf), abfd) != sizeof (buf))
ad86f1fb
TG
2375 return -1;
2376
2377 cmd->rebase_off = bfd_get_32 (abfd, buf + 0);
2378 cmd->rebase_size = bfd_get_32 (abfd, buf + 4);
2379 cmd->bind_off = bfd_get_32 (abfd, buf + 8);
2380 cmd->bind_size = bfd_get_32 (abfd, buf + 12);
2381 cmd->weak_bind_off = bfd_get_32 (abfd, buf + 16);
2382 cmd->weak_bind_size = bfd_get_32 (abfd, buf + 20);
2383 cmd->lazy_bind_off = bfd_get_32 (abfd, buf + 24);
2384 cmd->lazy_bind_size = bfd_get_32 (abfd, buf + 28);
2385 cmd->export_off = bfd_get_32 (abfd, buf + 32);
2386 cmd->export_size = bfd_get_32 (abfd, buf + 36);
2387 return 0;
2388}
2389
3af9a47b 2390static int
ab273af8
TG
2391bfd_mach_o_read_segment (bfd *abfd,
2392 bfd_mach_o_load_command *command,
2393 unsigned int wide)
3af9a47b 2394{
1e8a024a 2395 unsigned char buf[64];
3af9a47b
NC
2396 bfd_mach_o_segment_command *seg = &command->command.segment;
2397 unsigned long i;
a95a4550 2398
1e8a024a
TG
2399 if (wide)
2400 {
2401 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT_64);
3af9a47b 2402
c2f09c75 2403 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 2404 || bfd_bread ((void *) buf, 64, abfd) != 64)
1e8a024a 2405 return -1;
3af9a47b 2406
1e8a024a 2407 memcpy (seg->segname, buf, 16);
15e1c58a 2408 seg->segname[16] = '\0';
1e8a024a
TG
2409
2410 seg->vmaddr = bfd_h_get_64 (abfd, buf + 16);
2411 seg->vmsize = bfd_h_get_64 (abfd, buf + 24);
2412 seg->fileoff = bfd_h_get_64 (abfd, buf + 32);
2413 seg->filesize = bfd_h_get_64 (abfd, buf + 40);
2414 seg->maxprot = bfd_h_get_32 (abfd, buf + 48);
2415 seg->initprot = bfd_h_get_32 (abfd, buf + 52);
2416 seg->nsects = bfd_h_get_32 (abfd, buf + 56);
2417 seg->flags = bfd_h_get_32 (abfd, buf + 60);
2418 }
2419 else
2420 {
2421 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
2422
c2f09c75 2423 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 2424 || bfd_bread ((void *) buf, 48, abfd) != 48)
1e8a024a
TG
2425 return -1;
2426
2427 memcpy (seg->segname, buf, 16);
15e1c58a 2428 seg->segname[16] = '\0';
1e8a024a
TG
2429
2430 seg->vmaddr = bfd_h_get_32 (abfd, buf + 16);
2431 seg->vmsize = bfd_h_get_32 (abfd, buf + 20);
2432 seg->fileoff = bfd_h_get_32 (abfd, buf + 24);
2433 seg->filesize = bfd_h_get_32 (abfd, buf + 28);
2434 seg->maxprot = bfd_h_get_32 (abfd, buf + 32);
2435 seg->initprot = bfd_h_get_32 (abfd, buf + 36);
2436 seg->nsects = bfd_h_get_32 (abfd, buf + 40);
2437 seg->flags = bfd_h_get_32 (abfd, buf + 44);
2438 }
3af9a47b 2439
3af9a47b
NC
2440 if (seg->nsects != 0)
2441 {
154a1ee5
TG
2442 seg->sections = bfd_alloc (abfd, seg->nsects
2443 * sizeof (bfd_mach_o_section));
3af9a47b
NC
2444 if (seg->sections == NULL)
2445 return -1;
a95a4550 2446
3af9a47b
NC
2447 for (i = 0; i < seg->nsects; i++)
2448 {
1e8a024a 2449 bfd_vma segoff;
154a1ee5 2450 if (wide)
c2f09c75 2451 segoff = command->offset + BFD_MACH_O_LC_SEGMENT_64_SIZE
154a1ee5
TG
2452 + (i * BFD_MACH_O_SECTION_64_SIZE);
2453 else
c2f09c75 2454 segoff = command->offset + BFD_MACH_O_LC_SEGMENT_SIZE
154a1ee5 2455 + (i * BFD_MACH_O_SECTION_SIZE);
3af9a47b 2456
ab273af8 2457 if (bfd_mach_o_read_section
15e1c58a 2458 (abfd, &seg->sections[i], segoff, seg->initprot, wide) != 0)
3af9a47b 2459 return -1;
a95a4550 2460 }
3af9a47b
NC
2461 }
2462
2463 return 0;
2464}
2465
1e8a024a 2466static int
ab273af8 2467bfd_mach_o_read_segment_32 (bfd *abfd, bfd_mach_o_load_command *command)
1e8a024a 2468{
ab273af8 2469 return bfd_mach_o_read_segment (abfd, command, 0);
1e8a024a
TG
2470}
2471
2472static int
ab273af8 2473bfd_mach_o_read_segment_64 (bfd *abfd, bfd_mach_o_load_command *command)
1e8a024a 2474{
ab273af8 2475 return bfd_mach_o_read_segment (abfd, command, 1);
1e8a024a
TG
2476}
2477
3af9a47b 2478static int
ab273af8 2479bfd_mach_o_read_command (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
2480{
2481 unsigned char buf[8];
2482
046b007d 2483 /* Read command type and length. */
c2f09c75 2484 if (bfd_seek (abfd, command->offset, SEEK_SET) != 0
91d6fa6a 2485 || bfd_bread ((void *) buf, 8, abfd) != 8)
3af9a47b
NC
2486 return -1;
2487
154a1ee5 2488 command->type = bfd_h_get_32 (abfd, buf) & ~BFD_MACH_O_LC_REQ_DYLD;
e84d6fca 2489 command->type_required = (bfd_h_get_32 (abfd, buf) & BFD_MACH_O_LC_REQ_DYLD
154a1ee5 2490 ? TRUE : FALSE);
3af9a47b
NC
2491 command->len = bfd_h_get_32 (abfd, buf + 4);
2492
2493 switch (command->type)
2494 {
2495 case BFD_MACH_O_LC_SEGMENT:
ab273af8 2496 if (bfd_mach_o_read_segment_32 (abfd, command) != 0)
1e8a024a
TG
2497 return -1;
2498 break;
2499 case BFD_MACH_O_LC_SEGMENT_64:
ab273af8 2500 if (bfd_mach_o_read_segment_64 (abfd, command) != 0)
3af9a47b
NC
2501 return -1;
2502 break;
2503 case BFD_MACH_O_LC_SYMTAB:
ab273af8 2504 if (bfd_mach_o_read_symtab (abfd, command) != 0)
3af9a47b
NC
2505 return -1;
2506 break;
2507 case BFD_MACH_O_LC_SYMSEG:
2508 break;
2509 case BFD_MACH_O_LC_THREAD:
2510 case BFD_MACH_O_LC_UNIXTHREAD:
ab273af8 2511 if (bfd_mach_o_read_thread (abfd, command) != 0)
3af9a47b
NC
2512 return -1;
2513 break;
2514 case BFD_MACH_O_LC_LOAD_DYLINKER:
2515 case BFD_MACH_O_LC_ID_DYLINKER:
ab273af8 2516 if (bfd_mach_o_read_dylinker (abfd, command) != 0)
3af9a47b
NC
2517 return -1;
2518 break;
2519 case BFD_MACH_O_LC_LOAD_DYLIB:
2520 case BFD_MACH_O_LC_ID_DYLIB:
2521 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
046b007d 2522 case BFD_MACH_O_LC_REEXPORT_DYLIB:
ab273af8 2523 if (bfd_mach_o_read_dylib (abfd, command) != 0)
3af9a47b
NC
2524 return -1;
2525 break;
2526 case BFD_MACH_O_LC_PREBOUND_DYLIB:
ab273af8 2527 if (bfd_mach_o_read_prebound_dylib (abfd, command) != 0)
3af9a47b
NC
2528 return -1;
2529 break;
2530 case BFD_MACH_O_LC_LOADFVMLIB:
2531 case BFD_MACH_O_LC_IDFVMLIB:
2532 case BFD_MACH_O_LC_IDENT:
2533 case BFD_MACH_O_LC_FVMFILE:
2534 case BFD_MACH_O_LC_PREPAGE:
2535 case BFD_MACH_O_LC_ROUTINES:
9b02d212 2536 case BFD_MACH_O_LC_ROUTINES_64:
046b007d 2537 break;
3af9a47b 2538 case BFD_MACH_O_LC_SUB_FRAMEWORK:
046b007d
TG
2539 case BFD_MACH_O_LC_SUB_UMBRELLA:
2540 case BFD_MACH_O_LC_SUB_LIBRARY:
2541 case BFD_MACH_O_LC_SUB_CLIENT:
0c9b2b4c 2542 case BFD_MACH_O_LC_RPATH:
ab273af8 2543 if (bfd_mach_o_read_str (abfd, command) != 0)
046b007d 2544 return -1;
3af9a47b
NC
2545 break;
2546 case BFD_MACH_O_LC_DYSYMTAB:
ab273af8 2547 if (bfd_mach_o_read_dysymtab (abfd, command) != 0)
3af9a47b
NC
2548 return -1;
2549 break;
3af9a47b
NC
2550 case BFD_MACH_O_LC_TWOLEVEL_HINTS:
2551 case BFD_MACH_O_LC_PREBIND_CKSUM:
2552 break;
15e1c58a 2553 case BFD_MACH_O_LC_UUID:
ab273af8 2554 if (bfd_mach_o_read_uuid (abfd, command) != 0)
15e1c58a
TG
2555 return -1;
2556 break;
2557 case BFD_MACH_O_LC_CODE_SIGNATURE:
846b9259 2558 case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO:
ab273af8 2559 if (bfd_mach_o_read_linkedit (abfd, command) != 0)
046b007d 2560 return -1;
15e1c58a 2561 break;
ad86f1fb 2562 case BFD_MACH_O_LC_DYLD_INFO:
ab273af8 2563 if (bfd_mach_o_read_dyld_info (abfd, command) != 0)
ad86f1fb
TG
2564 return -1;
2565 break;
3af9a47b 2566 default:
4a97a0e5
AM
2567 (*_bfd_error_handler) (_("unable to read unknown load command 0x%lx"),
2568 (unsigned long) command->type);
3af9a47b
NC
2569 break;
2570 }
2571
2572 return 0;
2573}
2574
2575static void
116c20d2 2576bfd_mach_o_flatten_sections (bfd *abfd)
3af9a47b 2577{
046b007d 2578 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b
NC
2579 long csect = 0;
2580 unsigned long i, j;
a95a4550 2581
15e1c58a 2582 /* Count total number of sections. */
3af9a47b
NC
2583 mdata->nsects = 0;
2584
2585 for (i = 0; i < mdata->header.ncmds; i++)
2586 {
1e8a024a
TG
2587 if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT
2588 || mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT_64)
3af9a47b 2589 {
e84d6fca
AM
2590 bfd_mach_o_segment_command *seg;
2591
2592 seg = &mdata->commands[i].command.segment;
3af9a47b
NC
2593 mdata->nsects += seg->nsects;
2594 }
2595 }
2596
15e1c58a 2597 /* Allocate sections array. */
e84d6fca
AM
2598 mdata->sections = bfd_alloc (abfd,
2599 mdata->nsects * sizeof (bfd_mach_o_section *));
15e1c58a
TG
2600
2601 /* Fill the array. */
3af9a47b
NC
2602 csect = 0;
2603
2604 for (i = 0; i < mdata->header.ncmds; i++)
2605 {
1e8a024a
TG
2606 if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT
2607 || mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT_64)
3af9a47b 2608 {
e84d6fca 2609 bfd_mach_o_segment_command *seg;
3af9a47b 2610
e84d6fca 2611 seg = &mdata->commands[i].command.segment;
3af9a47b
NC
2612 BFD_ASSERT (csect + seg->nsects <= mdata->nsects);
2613
2614 for (j = 0; j < seg->nsects; j++)
2615 mdata->sections[csect++] = &seg->sections[j];
2616 }
2617 }
2618}
2619
2620int
116c20d2 2621bfd_mach_o_scan_start_address (bfd *abfd)
3af9a47b 2622{
046b007d 2623 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b
NC
2624 bfd_mach_o_thread_command *cmd = NULL;
2625 unsigned long i;
2626
2627 for (i = 0; i < mdata->header.ncmds; i++)
2628 {
2629 if ((mdata->commands[i].type == BFD_MACH_O_LC_THREAD) ||
2630 (mdata->commands[i].type == BFD_MACH_O_LC_UNIXTHREAD))
2631 {
2632 if (cmd == NULL)
2633 cmd = &mdata->commands[i].command.thread;
2634 else
2635 return 0;
2636 }
2637 }
2638
2639 if (cmd == NULL)
2640 return 0;
2641
2642 for (i = 0; i < cmd->nflavours; i++)
2643 {
a95a4550 2644 if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_I386)
e84d6fca 2645 && (cmd->flavours[i].flavour
15e1c58a 2646 == (unsigned long) BFD_MACH_O_x86_THREAD_STATE32))
3af9a47b
NC
2647 {
2648 unsigned char buf[4];
2649
c2f09c75
TG
2650 if (bfd_seek (abfd, cmd->flavours[i].offset + 40, SEEK_SET) != 0
2651 || bfd_bread (buf, 4, abfd) != 4)
3af9a47b
NC
2652 return -1;
2653
2654 abfd->start_address = bfd_h_get_32 (abfd, buf);
2655 }
a95a4550 2656 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC)
3af9a47b
NC
2657 && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE))
2658 {
2659 unsigned char buf[4];
2660
c2f09c75
TG
2661 if (bfd_seek (abfd, cmd->flavours[i].offset + 0, SEEK_SET) != 0
2662 || bfd_bread (buf, 4, abfd) != 4)
3af9a47b
NC
2663 return -1;
2664
2665 abfd->start_address = bfd_h_get_32 (abfd, buf);
2666 }
1e8a024a 2667 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC_64)
b32e07d7 2668 && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE64))
1e8a024a
TG
2669 {
2670 unsigned char buf[8];
2671
c2f09c75
TG
2672 if (bfd_seek (abfd, cmd->flavours[i].offset + 0, SEEK_SET) != 0
2673 || bfd_bread (buf, 8, abfd) != 8)
1e8a024a
TG
2674 return -1;
2675
2676 abfd->start_address = bfd_h_get_64 (abfd, buf);
2677 }
2678 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_X86_64)
2679 && (cmd->flavours[i].flavour == BFD_MACH_O_x86_THREAD_STATE64))
2680 {
2681 unsigned char buf[8];
2682
c2f09c75
TG
2683 if (bfd_seek (abfd, cmd->flavours[i].offset + (16 * 8), SEEK_SET) != 0
2684 || bfd_bread (buf, 8, abfd) != 8)
1e8a024a
TG
2685 return -1;
2686
2687 abfd->start_address = bfd_h_get_64 (abfd, buf);
2688 }
3af9a47b
NC
2689 }
2690
2691 return 0;
2692}
2693
42fa0891
TG
2694bfd_boolean
2695bfd_mach_o_set_arch_mach (bfd *abfd,
2696 enum bfd_architecture arch,
2697 unsigned long machine)
2698{
2699 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
2700
2701 /* If this isn't the right architecture for this backend, and this
2702 isn't the generic backend, fail. */
2703 if (arch != bed->arch
2704 && arch != bfd_arch_unknown
2705 && bed->arch != bfd_arch_unknown)
2706 return FALSE;
2707
2708 return bfd_default_set_arch_mach (abfd, arch, machine);
2709}
2710
3af9a47b 2711int
116c20d2
NC
2712bfd_mach_o_scan (bfd *abfd,
2713 bfd_mach_o_header *header,
2714 bfd_mach_o_data_struct *mdata)
3af9a47b
NC
2715{
2716 unsigned int i;
3af9a47b
NC
2717 enum bfd_architecture cputype;
2718 unsigned long cpusubtype;
1e8a024a
TG
2719 unsigned int hdrsize;
2720
c2f09c75 2721 hdrsize = mach_o_wide_p (header) ?
154a1ee5 2722 BFD_MACH_O_HEADER_64_SIZE : BFD_MACH_O_HEADER_SIZE;
3af9a47b 2723
3af9a47b 2724 mdata->header = *header;
3af9a47b 2725
154a1ee5 2726 abfd->flags = abfd->flags & BFD_IN_MEMORY;
15e1c58a
TG
2727 switch (header->filetype)
2728 {
2729 case BFD_MACH_O_MH_OBJECT:
2730 abfd->flags |= HAS_RELOC;
2731 break;
2732 case BFD_MACH_O_MH_EXECUTE:
2733 abfd->flags |= EXEC_P;
2734 break;
2735 case BFD_MACH_O_MH_DYLIB:
2736 case BFD_MACH_O_MH_BUNDLE:
2737 abfd->flags |= DYNAMIC;
2738 break;
2739 }
2740
3af9a47b
NC
2741 abfd->tdata.mach_o_data = mdata;
2742
e84d6fca
AM
2743 bfd_mach_o_convert_architecture (header->cputype, header->cpusubtype,
2744 &cputype, &cpusubtype);
3af9a47b
NC
2745 if (cputype == bfd_arch_unknown)
2746 {
4a97a0e5
AM
2747 (*_bfd_error_handler) (_("bfd_mach_o_scan: unknown architecture 0x%lx/0x%lx"),
2748 header->cputype, header->cpusubtype);
3af9a47b
NC
2749 return -1;
2750 }
2751
2752 bfd_set_arch_mach (abfd, cputype, cpusubtype);
a95a4550 2753
3af9a47b
NC
2754 if (header->ncmds != 0)
2755 {
046b007d
TG
2756 mdata->commands = bfd_alloc
2757 (abfd, header->ncmds * sizeof (bfd_mach_o_load_command));
3af9a47b
NC
2758 if (mdata->commands == NULL)
2759 return -1;
a95a4550 2760
3af9a47b
NC
2761 for (i = 0; i < header->ncmds; i++)
2762 {
2763 bfd_mach_o_load_command *cur = &mdata->commands[i];
2764
2765 if (i == 0)
1e8a024a 2766 cur->offset = hdrsize;
3af9a47b
NC
2767 else
2768 {
2769 bfd_mach_o_load_command *prev = &mdata->commands[i - 1];
2770 cur->offset = prev->offset + prev->len;
2771 }
2772
ab273af8 2773 if (bfd_mach_o_read_command (abfd, cur) < 0)
3af9a47b 2774 return -1;
a95a4550 2775 }
3af9a47b
NC
2776 }
2777
2778 if (bfd_mach_o_scan_start_address (abfd) < 0)
7e3102a7 2779 return -1;
3af9a47b
NC
2780
2781 bfd_mach_o_flatten_sections (abfd);
3af9a47b
NC
2782 return 0;
2783}
2784
b34976b6 2785bfd_boolean
154a1ee5 2786bfd_mach_o_mkobject_init (bfd *abfd)
3af9a47b
NC
2787{
2788 bfd_mach_o_data_struct *mdata = NULL;
2789
116c20d2 2790 mdata = bfd_alloc (abfd, sizeof (bfd_mach_o_data_struct));
3af9a47b 2791 if (mdata == NULL)
b34976b6 2792 return FALSE;
3af9a47b
NC
2793 abfd->tdata.mach_o_data = mdata;
2794
2795 mdata->header.magic = 0;
2796 mdata->header.cputype = 0;
2797 mdata->header.cpusubtype = 0;
2798 mdata->header.filetype = 0;
2799 mdata->header.ncmds = 0;
2800 mdata->header.sizeofcmds = 0;
2801 mdata->header.flags = 0;
2802 mdata->header.byteorder = BFD_ENDIAN_UNKNOWN;
2803 mdata->commands = NULL;
3af9a47b
NC
2804 mdata->nsects = 0;
2805 mdata->sections = NULL;
3af9a47b 2806
b34976b6 2807 return TRUE;
3af9a47b
NC
2808}
2809
42fa0891
TG
2810static bfd_boolean
2811bfd_mach_o_gen_mkobject (bfd *abfd)
2812{
2813 bfd_mach_o_data_struct *mdata;
2814
2815 if (!bfd_mach_o_mkobject_init (abfd))
2816 return FALSE;
2817
2818 mdata = bfd_mach_o_get_data (abfd);
2819 mdata->header.magic = BFD_MACH_O_MH_MAGIC;
2820 mdata->header.cputype = 0;
2821 mdata->header.cpusubtype = 0;
2822 mdata->header.byteorder = abfd->xvec->byteorder;
2823 mdata->header.version = 1;
2824
2825 return TRUE;
2826}
2827
3af9a47b 2828const bfd_target *
154a1ee5
TG
2829bfd_mach_o_header_p (bfd *abfd,
2830 bfd_mach_o_filetype filetype,
2831 bfd_mach_o_cpu_type cputype)
3af9a47b 2832{
e84d6fca 2833 struct bfd_preserve preserve;
3af9a47b
NC
2834 bfd_mach_o_header header;
2835
e84d6fca 2836 preserve.marker = NULL;
154a1ee5 2837 if (!bfd_mach_o_read_header (abfd, &header))
e84d6fca 2838 goto wrong;
3af9a47b 2839
e84d6fca
AM
2840 if (! (header.byteorder == BFD_ENDIAN_BIG
2841 || header.byteorder == BFD_ENDIAN_LITTLE))
3af9a47b 2842 {
4a97a0e5
AM
2843 (*_bfd_error_handler) (_("unknown header byte-order value 0x%lx"),
2844 (unsigned long) header.byteorder);
e84d6fca 2845 goto wrong;
3af9a47b
NC
2846 }
2847
e84d6fca
AM
2848 if (! ((header.byteorder == BFD_ENDIAN_BIG
2849 && abfd->xvec->byteorder == BFD_ENDIAN_BIG
2850 && abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
2851 || (header.byteorder == BFD_ENDIAN_LITTLE
2852 && abfd->xvec->byteorder == BFD_ENDIAN_LITTLE
2853 && abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)))
2854 goto wrong;
3af9a47b 2855
154a1ee5
TG
2856 /* Check cputype and filetype.
2857 In case of wildcard, do not accept magics that are handled by existing
2858 targets. */
2859 if (cputype)
2860 {
2861 if (header.cputype != cputype)
2862 goto wrong;
2863 }
2864 else
2865 {
2866 switch (header.cputype)
2867 {
2868 case BFD_MACH_O_CPU_TYPE_I386:
2869 /* Handled by mach-o-i386 */
2870 goto wrong;
2871 default:
2872 break;
2873 }
2874 }
2875 if (filetype)
2876 {
2877 if (header.filetype != filetype)
2878 goto wrong;
2879 }
2880 else
2881 {
2882 switch (header.filetype)
2883 {
2884 case BFD_MACH_O_MH_CORE:
2885 /* Handled by core_p */
2886 goto wrong;
2887 default:
2888 break;
2889 }
2890 }
2891
e84d6fca
AM
2892 preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct));
2893 if (preserve.marker == NULL
2894 || !bfd_preserve_save (abfd, &preserve))
2895 goto fail;
3af9a47b 2896
e84d6fca
AM
2897 if (bfd_mach_o_scan (abfd, &header,
2898 (bfd_mach_o_data_struct *) preserve.marker) != 0)
2899 goto wrong;
a95a4550 2900
e84d6fca 2901 bfd_preserve_finish (abfd, &preserve);
3af9a47b 2902 return abfd->xvec;
e84d6fca
AM
2903
2904 wrong:
2905 bfd_set_error (bfd_error_wrong_format);
2906
2907 fail:
2908 if (preserve.marker != NULL)
2909 bfd_preserve_restore (abfd, &preserve);
2910 return NULL;
3af9a47b
NC
2911}
2912
154a1ee5
TG
2913static const bfd_target *
2914bfd_mach_o_gen_object_p (bfd *abfd)
3af9a47b 2915{
154a1ee5
TG
2916 return bfd_mach_o_header_p (abfd, 0, 0);
2917}
e84d6fca 2918
154a1ee5
TG
2919static const bfd_target *
2920bfd_mach_o_gen_core_p (bfd *abfd)
2921{
2922 return bfd_mach_o_header_p (abfd, BFD_MACH_O_MH_CORE, 0);
3af9a47b
NC
2923}
2924
2925typedef struct mach_o_fat_archentry
2926{
2927 unsigned long cputype;
2928 unsigned long cpusubtype;
2929 unsigned long offset;
2930 unsigned long size;
2931 unsigned long align;
3af9a47b
NC
2932} mach_o_fat_archentry;
2933
2934typedef struct mach_o_fat_data_struct
2935{
2936 unsigned long magic;
2937 unsigned long nfat_arch;
2938 mach_o_fat_archentry *archentries;
2939} mach_o_fat_data_struct;
2940
2941const bfd_target *
116c20d2 2942bfd_mach_o_archive_p (bfd *abfd)
3af9a47b 2943{
e84d6fca 2944 mach_o_fat_data_struct *adata = NULL;
3af9a47b
NC
2945 unsigned char buf[20];
2946 unsigned long i;
2947
c2f09c75 2948 if (bfd_seek (abfd, 0, SEEK_SET) != 0
91d6fa6a 2949 || bfd_bread ((void *) buf, 8, abfd) != 8)
e84d6fca 2950 goto error;
3af9a47b 2951
116c20d2 2952 adata = bfd_alloc (abfd, sizeof (mach_o_fat_data_struct));
3af9a47b 2953 if (adata == NULL)
e84d6fca 2954 goto error;
a95a4550 2955
3af9a47b
NC
2956 adata->magic = bfd_getb32 (buf);
2957 adata->nfat_arch = bfd_getb32 (buf + 4);
2958 if (adata->magic != 0xcafebabe)
e84d6fca 2959 goto error;
27cc28f9
AS
2960 /* Avoid matching Java bytecode files, which have the same magic number.
2961 In the Java bytecode file format this field contains the JVM version,
2962 which starts at 43.0. */
2963 if (adata->nfat_arch > 30)
2964 goto error;
3af9a47b 2965
c2f09c75 2966 adata->archentries =
3af9a47b
NC
2967 bfd_alloc (abfd, adata->nfat_arch * sizeof (mach_o_fat_archentry));
2968 if (adata->archentries == NULL)
e84d6fca 2969 goto error;
3af9a47b
NC
2970
2971 for (i = 0; i < adata->nfat_arch; i++)
2972 {
c2f09c75 2973 if (bfd_seek (abfd, 8 + 20 * i, SEEK_SET) != 0
91d6fa6a 2974 || bfd_bread ((void *) buf, 20, abfd) != 20)
e84d6fca 2975 goto error;
3af9a47b
NC
2976 adata->archentries[i].cputype = bfd_getb32 (buf);
2977 adata->archentries[i].cpusubtype = bfd_getb32 (buf + 4);
2978 adata->archentries[i].offset = bfd_getb32 (buf + 8);
2979 adata->archentries[i].size = bfd_getb32 (buf + 12);
2980 adata->archentries[i].align = bfd_getb32 (buf + 16);
3af9a47b
NC
2981 }
2982
2983 abfd->tdata.mach_o_fat_data = adata;
2984 return abfd->xvec;
e84d6fca
AM
2985
2986 error:
2987 if (adata != NULL)
2988 bfd_release (abfd, adata);
2989 bfd_set_error (bfd_error_wrong_format);
2990 return NULL;
3af9a47b
NC
2991}
2992
2993bfd *
116c20d2 2994bfd_mach_o_openr_next_archived_file (bfd *archive, bfd *prev)
3af9a47b 2995{
e84d6fca 2996 mach_o_fat_data_struct *adata;
3af9a47b
NC
2997 mach_o_fat_archentry *entry = NULL;
2998 unsigned long i;
15e1c58a 2999 bfd *nbfd;
15e1c58a
TG
3000 enum bfd_architecture arch_type;
3001 unsigned long arch_subtype;
3af9a47b 3002
e84d6fca 3003 adata = (mach_o_fat_data_struct *) archive->tdata.mach_o_fat_data;
3af9a47b
NC
3004 BFD_ASSERT (adata != NULL);
3005
3006 /* Find index of previous entry. */
3007 if (prev == NULL)
3008 i = 0; /* Start at first one. */
3009 else
3010 {
3011 for (i = 0; i < adata->nfat_arch; i++)
3012 {
15e1c58a 3013 if (adata->archentries[i].offset == prev->origin)
3af9a47b
NC
3014 break;
3015 }
3016
3017 if (i == adata->nfat_arch)
3018 {
3019 /* Not found. */
3020 bfd_set_error (bfd_error_bad_value);
a95a4550 3021 return NULL;
3af9a47b
NC
3022 }
3023 i++; /* Get next entry. */
3024 }
a95a4550 3025
3af9a47b
NC
3026 if (i >= adata->nfat_arch)
3027 {
3028 bfd_set_error (bfd_error_no_more_archived_files);
3029 return NULL;
3030 }
3031
3032 entry = &adata->archentries[i];
15e1c58a
TG
3033 nbfd = _bfd_new_bfd_contained_in (archive);
3034 if (nbfd == NULL)
3035 return NULL;
3036
3037 nbfd->origin = entry->offset;
3038
3039 bfd_mach_o_convert_architecture (entry->cputype, entry->cpusubtype,
3040 &arch_type, &arch_subtype);
846b9259
TG
3041 /* Create the member filename.
3042 Use FILENAME:ARCH_NAME. */
3043 {
3044 char *s = NULL;
3045 const char *arch_name;
3046 size_t arch_file_len = strlen (bfd_get_filename (archive));
3047
3048 arch_name = bfd_printable_arch_mach (arch_type, arch_subtype);
3049 s = bfd_malloc (arch_file_len + 1 + strlen (arch_name) + 1);
3050 if (s == NULL)
3051 return NULL;
3052 memcpy (s, bfd_get_filename (archive), arch_file_len);
3053 s[arch_file_len] = ':';
3054 strcpy (s + arch_file_len + 1, arch_name);
3055 nbfd->filename = s;
3056 }
15e1c58a 3057 nbfd->iostream = NULL;
846b9259 3058 bfd_set_arch_mach (nbfd, arch_type, arch_subtype);
3af9a47b 3059
15e1c58a 3060 return nbfd;
3af9a47b
NC
3061}
3062
846b9259
TG
3063/* If ABFD format is FORMAT and architecture is ARCH, return it.
3064 If ABFD is a fat image containing a member that corresponds to FORMAT
3065 and ARCH, returns it.
3066 In other case, returns NULL.
3067 This function allows transparent uses of fat images. */
3068bfd *
3069bfd_mach_o_fat_extract (bfd *abfd,
3070 bfd_format format,
3071 const bfd_arch_info_type *arch)
3072{
3073 bfd *res;
3074 mach_o_fat_data_struct *adata;
3075 unsigned int i;
3076
3077 if (bfd_check_format (abfd, format))
3078 {
3079 if (bfd_get_arch_info (abfd) == arch)
3080 return abfd;
3081 return NULL;
3082 }
3083 if (!bfd_check_format (abfd, bfd_archive)
3084 || abfd->xvec != &mach_o_fat_vec)
3085 return NULL;
c2f09c75 3086
846b9259
TG
3087 /* This is a Mach-O fat image. */
3088 adata = (mach_o_fat_data_struct *) abfd->tdata.mach_o_fat_data;
3089 BFD_ASSERT (adata != NULL);
3090
3091 for (i = 0; i < adata->nfat_arch; i++)
3092 {
3093 struct mach_o_fat_archentry *e = &adata->archentries[i];
3094 enum bfd_architecture cpu_type;
3095 unsigned long cpu_subtype;
3096
3097 bfd_mach_o_convert_architecture (e->cputype, e->cpusubtype,
3098 &cpu_type, &cpu_subtype);
3099 if (cpu_type != arch->arch || cpu_subtype != arch->mach)
3100 continue;
3101
3102 /* The architecture is found. */
3103 res = _bfd_new_bfd_contained_in (abfd);
3104 if (res == NULL)
3105 return NULL;
3106
3107 res->origin = e->offset;
3108
3109 res->filename = strdup (abfd->filename);
3110 res->iostream = NULL;
3111
3112 if (bfd_check_format (res, format))
3113 {
3114 BFD_ASSERT (bfd_get_arch_info (res) == arch);
3115 return res;
3116 }
3117 bfd_close (res);
3118 return NULL;
3119 }
3120
3121 return NULL;
3122}
3123
e84d6fca 3124int
116c20d2
NC
3125bfd_mach_o_lookup_section (bfd *abfd,
3126 asection *section,
3127 bfd_mach_o_load_command **mcommand,
3128 bfd_mach_o_section **msection)
3af9a47b 3129{
046b007d 3130 struct mach_o_data_struct *md = bfd_mach_o_get_data (abfd);
3af9a47b
NC
3131 unsigned int i, j, num;
3132
3133 bfd_mach_o_load_command *ncmd = NULL;
3134 bfd_mach_o_section *nsect = NULL;
3135
3136 BFD_ASSERT (mcommand != NULL);
3137 BFD_ASSERT (msection != NULL);
3138
3139 num = 0;
3140 for (i = 0; i < md->header.ncmds; i++)
3141 {
3142 struct bfd_mach_o_load_command *cmd = &md->commands[i];
3143 struct bfd_mach_o_segment_command *seg = NULL;
3144
1e8a024a
TG
3145 if (cmd->type != BFD_MACH_O_LC_SEGMENT
3146 || cmd->type != BFD_MACH_O_LC_SEGMENT_64)
3af9a47b
NC
3147 continue;
3148 seg = &cmd->command.segment;
a95a4550 3149
3af9a47b
NC
3150 for (j = 0; j < seg->nsects; j++)
3151 {
3152 struct bfd_mach_o_section *sect = &seg->sections[j];
3153
3154 if (sect->bfdsection == section)
3155 {
3156 if (num == 0)
b32e07d7
TG
3157 {
3158 nsect = sect;
3159 ncmd = cmd;
3160 }
3af9a47b
NC
3161 num++;
3162 }
3163 }
3164 }
a95a4550 3165
3af9a47b
NC
3166 *mcommand = ncmd;
3167 *msection = nsect;
3168 return num;
3169}
3170
3171int
116c20d2
NC
3172bfd_mach_o_lookup_command (bfd *abfd,
3173 bfd_mach_o_load_command_type type,
3174 bfd_mach_o_load_command **mcommand)
3af9a47b 3175{
046b007d 3176 struct mach_o_data_struct *md = bfd_mach_o_get_data (abfd);
3af9a47b
NC
3177 bfd_mach_o_load_command *ncmd = NULL;
3178 unsigned int i, num;
3179
3af9a47b
NC
3180 BFD_ASSERT (md != NULL);
3181 BFD_ASSERT (mcommand != NULL);
3182
3183 num = 0;
3184 for (i = 0; i < md->header.ncmds; i++)
3185 {
3186 struct bfd_mach_o_load_command *cmd = &md->commands[i];
3187
3188 if (cmd->type != type)
3189 continue;
3190
3191 if (num == 0)
3192 ncmd = cmd;
3193 num++;
3194 }
3195
3196 *mcommand = ncmd;
3197 return num;
3198}
3199
3200unsigned long
116c20d2 3201bfd_mach_o_stack_addr (enum bfd_mach_o_cpu_type type)
3af9a47b
NC
3202{
3203 switch (type)
3204 {
3205 case BFD_MACH_O_CPU_TYPE_MC680x0:
3206 return 0x04000000;
3207 case BFD_MACH_O_CPU_TYPE_MC88000:
3208 return 0xffffe000;
3209 case BFD_MACH_O_CPU_TYPE_POWERPC:
3210 return 0xc0000000;
3211 case BFD_MACH_O_CPU_TYPE_I386:
3212 return 0xc0000000;
3213 case BFD_MACH_O_CPU_TYPE_SPARC:
3214 return 0xf0000000;
3215 case BFD_MACH_O_CPU_TYPE_I860:
3216 return 0;
3217 case BFD_MACH_O_CPU_TYPE_HPPA:
e84d6fca 3218 return 0xc0000000 - 0x04000000;
3af9a47b
NC
3219 default:
3220 return 0;
3221 }
3222}
3223
046b007d 3224typedef struct bfd_mach_o_xlat_name
15e1c58a 3225{
046b007d
TG
3226 const char *name;
3227 unsigned long val;
3228}
3229bfd_mach_o_xlat_name;
3230
3231static void
3232bfd_mach_o_print_flags (const bfd_mach_o_xlat_name *table,
3233 unsigned long val,
3234 FILE *file)
3235{
3236 int first = 1;
3237
3238 for (; table->name; table++)
3239 {
3240 if (table->val & val)
3241 {
3242 if (!first)
3243 fprintf (file, "+");
3244 fprintf (file, "%s", table->name);
3245 val &= ~table->val;
3246 first = 0;
3247 }
3248 }
3249 if (val)
3250 {
3251 if (!first)
3252 fprintf (file, "+");
3253 fprintf (file, "0x%lx", val);
3254 return;
3255 }
3256 if (first)
3257 fprintf (file, "-");
3258}
3259
3260static const char *
3261bfd_mach_o_get_name (const bfd_mach_o_xlat_name *table, unsigned long val)
3262{
3263 for (; table->name; table++)
3264 if (table->val == val)
3265 return table->name;
3266 return "*UNKNOWN*";
3267}
3268
3269static bfd_mach_o_xlat_name bfd_mach_o_cpu_name[] =
3270{
afecc97c
TG
3271 { "vax", BFD_MACH_O_CPU_TYPE_VAX },
3272 { "mc680x0", BFD_MACH_O_CPU_TYPE_MC680x0 },
3273 { "i386", BFD_MACH_O_CPU_TYPE_I386 },
3274 { "mips", BFD_MACH_O_CPU_TYPE_MIPS },
3275 { "mc98000", BFD_MACH_O_CPU_TYPE_MC98000 },
3276 { "hppa", BFD_MACH_O_CPU_TYPE_HPPA },
3277 { "arm", BFD_MACH_O_CPU_TYPE_ARM },
3278 { "mc88000", BFD_MACH_O_CPU_TYPE_MC88000 },
3279 { "sparc", BFD_MACH_O_CPU_TYPE_SPARC },
3280 { "i860", BFD_MACH_O_CPU_TYPE_I860 },
3281 { "alpha", BFD_MACH_O_CPU_TYPE_ALPHA },
3282 { "powerpc", BFD_MACH_O_CPU_TYPE_POWERPC },
3283 { "powerpc_64", BFD_MACH_O_CPU_TYPE_POWERPC_64 },
3284 { "x86_64", BFD_MACH_O_CPU_TYPE_X86_64 },
046b007d
TG
3285 { NULL, 0}
3286};
3287
3288static bfd_mach_o_xlat_name bfd_mach_o_filetype_name[] =
3289{
afecc97c
TG
3290 { "object", BFD_MACH_O_MH_OBJECT },
3291 { "execute", BFD_MACH_O_MH_EXECUTE },
3292 { "fvmlib", BFD_MACH_O_MH_FVMLIB },
3293 { "core", BFD_MACH_O_MH_CORE },
3294 { "preload", BFD_MACH_O_MH_PRELOAD },
3295 { "dylib", BFD_MACH_O_MH_DYLIB },
3296 { "dylinker", BFD_MACH_O_MH_DYLINKER },
3297 { "bundle", BFD_MACH_O_MH_BUNDLE },
3298 { "dylib_stub", BFD_MACH_O_MH_DYLIB_STUB },
3299 { "dym", BFD_MACH_O_MH_DSYM },
3300 { "kext_bundle", BFD_MACH_O_MH_KEXT_BUNDLE },
046b007d
TG
3301 { NULL, 0}
3302};
3303
3304static bfd_mach_o_xlat_name bfd_mach_o_header_flags_name[] =
3305{
3306 { "noundefs", BFD_MACH_O_MH_NOUNDEFS },
3307 { "incrlink", BFD_MACH_O_MH_INCRLINK },
3308 { "dyldlink", BFD_MACH_O_MH_DYLDLINK },
3309 { "bindatload", BFD_MACH_O_MH_BINDATLOAD },
3310 { "prebound", BFD_MACH_O_MH_PREBOUND },
3311 { "split_segs", BFD_MACH_O_MH_SPLIT_SEGS },
3312 { "lazy_init", BFD_MACH_O_MH_LAZY_INIT },
3313 { "twolevel", BFD_MACH_O_MH_TWOLEVEL },
3314 { "force_flat", BFD_MACH_O_MH_FORCE_FLAT },
3315 { "nomultidefs", BFD_MACH_O_MH_NOMULTIDEFS },
3316 { "nofixprebinding", BFD_MACH_O_MH_NOFIXPREBINDING },
3317 { "prebindable", BFD_MACH_O_MH_PREBINDABLE },
3318 { "allmodsbound", BFD_MACH_O_MH_ALLMODSBOUND },
3319 { "subsections_via_symbols", BFD_MACH_O_MH_SUBSECTIONS_VIA_SYMBOLS },
3320 { "canonical", BFD_MACH_O_MH_CANONICAL },
3321 { "weak_defines", BFD_MACH_O_MH_WEAK_DEFINES },
3322 { "binds_to_weak", BFD_MACH_O_MH_BINDS_TO_WEAK },
3323 { "allow_stack_execution", BFD_MACH_O_MH_ALLOW_STACK_EXECUTION },
3324 { "root_safe", BFD_MACH_O_MH_ROOT_SAFE },
3325 { "setuid_safe", BFD_MACH_O_MH_SETUID_SAFE },
3326 { "no_reexported_dylibs", BFD_MACH_O_MH_NO_REEXPORTED_DYLIBS },
3327 { "pie", BFD_MACH_O_MH_PIE },
3328 { NULL, 0}
3329};
3330
3331static bfd_mach_o_xlat_name bfd_mach_o_section_type_name[] =
3332{
3333 { "regular", BFD_MACH_O_S_REGULAR},
3334 { "zerofill", BFD_MACH_O_S_ZEROFILL},
3335 { "cstring_literals", BFD_MACH_O_S_CSTRING_LITERALS},
3336 { "4byte_literals", BFD_MACH_O_S_4BYTE_LITERALS},
3337 { "8byte_literals", BFD_MACH_O_S_8BYTE_LITERALS},
3338 { "literal_pointers", BFD_MACH_O_S_LITERAL_POINTERS},
3339 { "non_lazy_symbol_pointers", BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS},
3340 { "lazy_symbol_pointers", BFD_MACH_O_S_LAZY_SYMBOL_POINTERS},
3341 { "symbol_stubs", BFD_MACH_O_S_SYMBOL_STUBS},
3342 { "mod_init_func_pointers", BFD_MACH_O_S_MOD_INIT_FUNC_POINTERS},
3343 { "mod_fini_func_pointers", BFD_MACH_O_S_MOD_FINI_FUNC_POINTERS},
3344 { "coalesced", BFD_MACH_O_S_COALESCED},
3345 { "gb_zerofill", BFD_MACH_O_S_GB_ZEROFILL},
3346 { "interposing", BFD_MACH_O_S_INTERPOSING},
3347 { "16byte_literals", BFD_MACH_O_S_16BYTE_LITERALS},
3348 { "dtrace_dof", BFD_MACH_O_S_DTRACE_DOF},
3349 { "lazy_dylib_symbol_pointers", BFD_MACH_O_S_LAZY_DYLIB_SYMBOL_POINTERS},
3350 { NULL, 0}
3351};
3352
3353static bfd_mach_o_xlat_name bfd_mach_o_section_attribute_name[] =
3354{
3355 { "loc_reloc", BFD_MACH_O_S_ATTR_LOC_RELOC },
3356 { "ext_reloc", BFD_MACH_O_S_ATTR_EXT_RELOC },
3357 { "some_instructions", BFD_MACH_O_S_ATTR_SOME_INSTRUCTIONS },
3358 { "debug", BFD_MACH_O_S_ATTR_DEBUG },
3359 { "modifying_code", BFD_MACH_O_S_SELF_MODIFYING_CODE },
3360 { "live_support", BFD_MACH_O_S_ATTR_LIVE_SUPPORT },
3361 { "no_dead_strip", BFD_MACH_O_S_ATTR_NO_DEAD_STRIP },
3362 { "strip_static_syms", BFD_MACH_O_S_ATTR_STRIP_STATIC_SYMS },
3363 { "no_toc", BFD_MACH_O_S_ATTR_NO_TOC },
3364 { "pure_instructions", BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS },
3365 { NULL, 0}
3366};
3367
3368static bfd_mach_o_xlat_name bfd_mach_o_load_command_name[] =
3369{
3370 { "segment", BFD_MACH_O_LC_SEGMENT},
3371 { "symtab", BFD_MACH_O_LC_SYMTAB},
3372 { "symseg", BFD_MACH_O_LC_SYMSEG},
3373 { "thread", BFD_MACH_O_LC_THREAD},
3374 { "unixthread", BFD_MACH_O_LC_UNIXTHREAD},
3375 { "loadfvmlib", BFD_MACH_O_LC_LOADFVMLIB},
3376 { "idfvmlib", BFD_MACH_O_LC_IDFVMLIB},
3377 { "ident", BFD_MACH_O_LC_IDENT},
3378 { "fvmfile", BFD_MACH_O_LC_FVMFILE},
3379 { "prepage", BFD_MACH_O_LC_PREPAGE},
3380 { "dysymtab", BFD_MACH_O_LC_DYSYMTAB},
3381 { "load_dylib", BFD_MACH_O_LC_LOAD_DYLIB},
3382 { "id_dylib", BFD_MACH_O_LC_ID_DYLIB},
3383 { "load_dylinker", BFD_MACH_O_LC_LOAD_DYLINKER},
3384 { "id_dylinker", BFD_MACH_O_LC_ID_DYLINKER},
3385 { "prebound_dylib", BFD_MACH_O_LC_PREBOUND_DYLIB},
3386 { "routines", BFD_MACH_O_LC_ROUTINES},
3387 { "sub_framework", BFD_MACH_O_LC_SUB_FRAMEWORK},
3388 { "sub_umbrella", BFD_MACH_O_LC_SUB_UMBRELLA},
3389 { "sub_client", BFD_MACH_O_LC_SUB_CLIENT},
3390 { "sub_library", BFD_MACH_O_LC_SUB_LIBRARY},
3391 { "twolevel_hints", BFD_MACH_O_LC_TWOLEVEL_HINTS},
3392 { "prebind_cksum", BFD_MACH_O_LC_PREBIND_CKSUM},
3393 { "load_weak_dylib", BFD_MACH_O_LC_LOAD_WEAK_DYLIB},
3394 { "segment_64", BFD_MACH_O_LC_SEGMENT_64},
3395 { "routines_64", BFD_MACH_O_LC_ROUTINES_64},
3396 { "uuid", BFD_MACH_O_LC_UUID},
3397 { "rpath", BFD_MACH_O_LC_RPATH},
3398 { "code_signature", BFD_MACH_O_LC_CODE_SIGNATURE},
3399 { "segment_split_info", BFD_MACH_O_LC_SEGMENT_SPLIT_INFO},
3400 { "reexport_dylib", BFD_MACH_O_LC_REEXPORT_DYLIB},
3401 { "lazy_load_dylib", BFD_MACH_O_LC_LAZY_LOAD_DYLIB},
3402 { "encryption_info", BFD_MACH_O_LC_ENCRYPTION_INFO},
ad86f1fb 3403 { "dyld_info", BFD_MACH_O_LC_DYLD_INFO},
046b007d
TG
3404 { NULL, 0}
3405};
3406
3407static void
3408bfd_mach_o_print_private_header (bfd *abfd, FILE *file)
3409{
3410 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3411 bfd_mach_o_header *h = &mdata->header;
3412
afecc97c 3413 fputs (_("Mach-O header:\n"), file);
046b007d
TG
3414 fprintf (file, _(" magic : %08lx\n"), h->magic);
3415 fprintf (file, _(" cputype : %08lx (%s)\n"), h->cputype,
3416 bfd_mach_o_get_name (bfd_mach_o_cpu_name, h->cputype));
3417 fprintf (file, _(" cpusubtype: %08lx\n"), h->cpusubtype);
3418 fprintf (file, _(" filetype : %08lx (%s)\n"),
3419 h->filetype,
3420 bfd_mach_o_get_name (bfd_mach_o_filetype_name, h->filetype));
b2b62060 3421 fprintf (file, _(" ncmds : %08lx (%lu)\n"), h->ncmds, h->ncmds);
046b007d
TG
3422 fprintf (file, _(" sizeofcmds: %08lx\n"), h->sizeofcmds);
3423 fprintf (file, _(" flags : %08lx ("), h->flags);
3424 bfd_mach_o_print_flags (bfd_mach_o_header_flags_name, h->flags, file);
afecc97c 3425 fputs (_(")\n"), file);
b8674692 3426 fprintf (file, _(" reserved : %08x\n"), h->reserved);
046b007d
TG
3427}
3428
3429static void
3430bfd_mach_o_print_section_map (bfd *abfd, FILE *file)
3431{
3432 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
15e1c58a
TG
3433 unsigned int i, j;
3434 unsigned int sec_nbr = 0;
3435
afecc97c
TG
3436 fputs (_("Segments and Sections:\n"), file);
3437 fputs (_(" #: Segment name Section name Address\n"), file);
15e1c58a
TG
3438
3439 for (i = 0; i < mdata->header.ncmds; i++)
3440 {
3441 bfd_mach_o_segment_command *seg;
3442
3443 if (mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT
3444 && mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT_64)
3445 continue;
3446
3447 seg = &mdata->commands[i].command.segment;
3448
3449 fprintf (file, "[Segment %-16s ", seg->segname);
3450 fprintf_vma (file, seg->vmaddr);
3451 fprintf (file, "-");
3452 fprintf_vma (file, seg->vmaddr + seg->vmsize - 1);
3453 fputc (' ', file);
3454 fputc (seg->initprot & BFD_MACH_O_PROT_READ ? 'r' : '-', file);
3455 fputc (seg->initprot & BFD_MACH_O_PROT_WRITE ? 'w' : '-', file);
3456 fputc (seg->initprot & BFD_MACH_O_PROT_EXECUTE ? 'x' : '-', file);
3457 fprintf (file, "]\n");
3458 for (j = 0; j < seg->nsects; j++)
3459 {
3460 bfd_mach_o_section *sec = &seg->sections[j];
3461 fprintf (file, "%02u: %-16s %-16s ", ++sec_nbr,
3462 sec->segname, sec->sectname);
3463 fprintf_vma (file, sec->addr);
3464 fprintf (file, " ");
3465 fprintf_vma (file, sec->size);
3466 fprintf (file, " %08lx\n", sec->flags);
3467 }
3468 }
046b007d
TG
3469}
3470
046b007d
TG
3471static void
3472bfd_mach_o_print_section (bfd *abfd ATTRIBUTE_UNUSED,
3473 bfd_mach_o_section *sec, FILE *file)
3474{
b32e07d7
TG
3475 fprintf (file, " Section: %-16s %-16s (bfdname: %s)\n",
3476 sec->sectname, sec->segname, sec->bfdsection->name);
046b007d
TG
3477 fprintf (file, " addr: ");
3478 fprintf_vma (file, sec->addr);
3479 fprintf (file, " size: ");
3480 fprintf_vma (file, sec->size);
3481 fprintf (file, " offset: ");
3482 fprintf_vma (file, sec->offset);
3483 fprintf (file, "\n");
3484 fprintf (file, " align: %ld", sec->align);
3485 fprintf (file, " nreloc: %lu reloff: ", sec->nreloc);
3486 fprintf_vma (file, sec->reloff);
3487 fprintf (file, "\n");
3488 fprintf (file, " flags: %08lx (type: %s", sec->flags,
3489 bfd_mach_o_get_name (bfd_mach_o_section_type_name,
3490 sec->flags & BFD_MACH_O_SECTION_TYPE_MASK));
3491 fprintf (file, " attr: ");
3492 bfd_mach_o_print_flags (bfd_mach_o_section_attribute_name,
3493 sec->flags & BFD_MACH_O_SECTION_ATTRIBUTES_MASK,
3494 file);
3495 fprintf (file, ")\n");
3496 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
3497 {
3498 case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
3499 case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
3500 case BFD_MACH_O_S_SYMBOL_STUBS:
3501 fprintf (file, " first indirect sym: %lu", sec->reserved1);
3502 fprintf (file, " (%u entries)",
3503 bfd_mach_o_section_get_nbr_indirect (abfd, sec));
3504 break;
3505 default:
3506 fprintf (file, " reserved1: 0x%lx", sec->reserved1);
3507 break;
3508 }
3509 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
3510 {
3511 case BFD_MACH_O_S_SYMBOL_STUBS:
3512 fprintf (file, " stub size: %lu", sec->reserved2);
3513 break;
3514 default:
3515 fprintf (file, " reserved2: 0x%lx", sec->reserved2);
3516 break;
3517 }
3518 fprintf (file, " reserved3: 0x%lx\n", sec->reserved3);
3519}
3520
3521static void
3522bfd_mach_o_print_segment (bfd *abfd ATTRIBUTE_UNUSED,
3523 bfd_mach_o_load_command *cmd, FILE *file)
3524{
3525 bfd_mach_o_segment_command *seg = &cmd->command.segment;
3526 unsigned int i;
3527
b32e07d7 3528 fprintf (file, " name: %s\n", *seg->segname ? seg->segname : "*none*");
046b007d
TG
3529 fprintf (file, " vmaddr: ");
3530 fprintf_vma (file, seg->vmaddr);
3531 fprintf (file, " vmsize: ");
3532 fprintf_vma (file, seg->vmsize);
3533 fprintf (file, "\n");
3534 fprintf (file, " fileoff: ");
3535 fprintf_vma (file, seg->fileoff);
3536 fprintf (file, " filesize: ");
3537 fprintf_vma (file, (bfd_vma)seg->filesize);
3538 fprintf (file, " endoff: ");
3539 fprintf_vma (file, (bfd_vma)(seg->fileoff + seg->filesize));
3540 fprintf (file, "\n");
3541 fprintf (file, " nsects: %lu ", seg->nsects);
3542 fprintf (file, " flags: %lx\n", seg->flags);
3543 for (i = 0; i < seg->nsects; i++)
3544 bfd_mach_o_print_section (abfd, &seg->sections[i], file);
3545}
3546
3547static void
3548bfd_mach_o_print_dysymtab (bfd *abfd ATTRIBUTE_UNUSED,
3549 bfd_mach_o_load_command *cmd, FILE *file)
3550{
3551 bfd_mach_o_dysymtab_command *dysymtab = &cmd->command.dysymtab;
3552 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3553 unsigned int i;
3554
b32e07d7 3555 fprintf (file, " local symbols: idx: %10lu num: %-8lu",
046b007d 3556 dysymtab->ilocalsym, dysymtab->nlocalsym);
b32e07d7
TG
3557 fprintf (file, " (nxtidx: %lu)\n",
3558 dysymtab->ilocalsym + dysymtab->nlocalsym);
3559 fprintf (file, " external symbols: idx: %10lu num: %-8lu",
046b007d 3560 dysymtab->iextdefsym, dysymtab->nextdefsym);
b32e07d7
TG
3561 fprintf (file, " (nxtidx: %lu)\n",
3562 dysymtab->iextdefsym + dysymtab->nextdefsym);
3563 fprintf (file, " undefined symbols: idx: %10lu num: %-8lu",
046b007d 3564 dysymtab->iundefsym, dysymtab->nundefsym);
b32e07d7
TG
3565 fprintf (file, " (nxtidx: %lu)\n",
3566 dysymtab->iundefsym + dysymtab->nundefsym);
046b007d
TG
3567 fprintf (file, " table of content: off: 0x%08lx num: %-8lu",
3568 dysymtab->tocoff, dysymtab->ntoc);
3569 fprintf (file, " (endoff: 0x%08lx)\n",
3570 dysymtab->tocoff
3571 + dysymtab->ntoc * BFD_MACH_O_TABLE_OF_CONTENT_SIZE);
3572 fprintf (file, " module table: off: 0x%08lx num: %-8lu",
3573 dysymtab->modtaboff, dysymtab->nmodtab);
3574 fprintf (file, " (endoff: 0x%08lx)\n",
3575 dysymtab->modtaboff + dysymtab->nmodtab
3576 * (mach_o_wide_p (&mdata->header) ?
3577 BFD_MACH_O_DYLIB_MODULE_64_SIZE : BFD_MACH_O_DYLIB_MODULE_SIZE));
3578 fprintf (file, " external reference table: off: 0x%08lx num: %-8lu",
3579 dysymtab->extrefsymoff, dysymtab->nextrefsyms);
3580 fprintf (file, " (endoff: 0x%08lx)\n",
3581 dysymtab->extrefsymoff
3582 + dysymtab->nextrefsyms * BFD_MACH_O_REFERENCE_SIZE);
3583 fprintf (file, " indirect symbol table: off: 0x%08lx num: %-8lu",
3584 dysymtab->indirectsymoff, dysymtab->nindirectsyms);
3585 fprintf (file, " (endoff: 0x%08lx)\n",
3586 dysymtab->indirectsymoff
3587 + dysymtab->nindirectsyms * BFD_MACH_O_INDIRECT_SYMBOL_SIZE);
3588 fprintf (file, " external relocation table: off: 0x%08lx num: %-8lu",
3589 dysymtab->extreloff, dysymtab->nextrel);
3590 fprintf (file, " (endoff: 0x%08lx)\n",
3591 dysymtab->extreloff + dysymtab->nextrel * BFD_MACH_O_RELENT_SIZE);
3592 fprintf (file, " local relocation table: off: 0x%08lx num: %-8lu",
3593 dysymtab->locreloff, dysymtab->nlocrel);
3594 fprintf (file, " (endoff: 0x%08lx)\n",
3595 dysymtab->locreloff + dysymtab->nlocrel * BFD_MACH_O_RELENT_SIZE);
3596
3597 if (dysymtab->ntoc > 0
3598 || dysymtab->nindirectsyms > 0
3599 || dysymtab->nextrefsyms > 0)
3600 {
3601 /* Try to read the symbols to display the toc or indirect symbols. */
ab273af8 3602 bfd_mach_o_read_symtab_symbols (abfd);
046b007d
TG
3603 }
3604 else if (dysymtab->nmodtab > 0)
3605 {
3606 /* Try to read the strtab to display modules name. */
ab273af8 3607 bfd_mach_o_read_symtab_strtab (abfd);
046b007d
TG
3608 }
3609
3610 for (i = 0; i < dysymtab->nmodtab; i++)
3611 {
3612 bfd_mach_o_dylib_module *module = &dysymtab->dylib_module[i];
3613 fprintf (file, " module %u:\n", i);
3614 fprintf (file, " name: %lu", module->module_name_idx);
3615 if (mdata->symtab && mdata->symtab->strtab)
3616 fprintf (file, ": %s",
3617 mdata->symtab->strtab + module->module_name_idx);
3618 fprintf (file, "\n");
3619 fprintf (file, " extdefsym: idx: %8lu num: %lu\n",
3620 module->iextdefsym, module->nextdefsym);
3621 fprintf (file, " refsym: idx: %8lu num: %lu\n",
3622 module->irefsym, module->nrefsym);
3623 fprintf (file, " localsym: idx: %8lu num: %lu\n",
3624 module->ilocalsym, module->nlocalsym);
3625 fprintf (file, " extrel: idx: %8lu num: %lu\n",
3626 module->iextrel, module->nextrel);
3627 fprintf (file, " init: idx: %8u num: %u\n",
3628 module->iinit, module->ninit);
3629 fprintf (file, " term: idx: %8u num: %u\n",
3630 module->iterm, module->nterm);
3631 fprintf (file, " objc_module_info: addr: ");
3632 fprintf_vma (file, module->objc_module_info_addr);
3633 fprintf (file, " size: %lu\n", module->objc_module_info_size);
3634 }
3635
3636 if (dysymtab->ntoc > 0)
3637 {
3638 bfd_mach_o_symtab_command *symtab = mdata->symtab;
3639
3640 fprintf (file, " table of content: (symbol/module)\n");
3641 for (i = 0; i < dysymtab->ntoc; i++)
3642 {
3643 bfd_mach_o_dylib_table_of_content *toc = &dysymtab->dylib_toc[i];
3644
3645 fprintf (file, " %4u: ", i);
3646 if (symtab && symtab->symbols && toc->symbol_index < symtab->nsyms)
3647 {
3648 const char *name = symtab->symbols[toc->symbol_index].symbol.name;
3649 fprintf (file, "%s (%lu)", name ? name : "*invalid*",
3650 toc->symbol_index);
3651 }
3652 else
3653 fprintf (file, "%lu", toc->symbol_index);
3654
3655 fprintf (file, " / ");
3656 if (symtab && symtab->strtab
3657 && toc->module_index < dysymtab->nmodtab)
3658 {
3659 bfd_mach_o_dylib_module *mod;
3660 mod = &dysymtab->dylib_module[toc->module_index];
3661 fprintf (file, "%s (%lu)",
3662 symtab->strtab + mod->module_name_idx,
3663 toc->module_index);
3664 }
3665 else
3666 fprintf (file, "%lu", toc->module_index);
3667
3668 fprintf (file, "\n");
3669 }
3670 }
3671
3672 if (dysymtab->nindirectsyms != 0)
3673 {
3674 fprintf (file, " indirect symbols:\n");
3675
3676 for (i = 0; i < mdata->nsects; i++)
3677 {
3678 bfd_mach_o_section *sec = mdata->sections[i];
3679 unsigned int j, first, last;
3680 bfd_mach_o_symtab_command *symtab = mdata->symtab;
afecc97c
TG
3681 bfd_vma addr;
3682 bfd_vma entry_size;
046b007d
TG
3683
3684 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
3685 {
3686 case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
3687 case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
3688 case BFD_MACH_O_S_SYMBOL_STUBS:
3689 first = sec->reserved1;
3690 last = first + bfd_mach_o_section_get_nbr_indirect (abfd, sec);
afecc97c
TG
3691 addr = sec->addr;
3692 entry_size = bfd_mach_o_section_get_entry_size (abfd, sec);
046b007d
TG
3693 fprintf (file, " for section %s.%s:\n",
3694 sec->segname, sec->sectname);
3695 for (j = first; j < last; j++)
3696 {
3697 unsigned int isym = dysymtab->indirect_syms[j];
3698
afecc97c
TG
3699 fprintf (file, " ");
3700 fprintf_vma (file, addr);
3701 fprintf (file, " %5u: 0x%08x", j, isym);
046b007d
TG
3702 if (isym & BFD_MACH_O_INDIRECT_SYMBOL_LOCAL)
3703 fprintf (file, " LOCAL");
3704 if (isym & BFD_MACH_O_INDIRECT_SYMBOL_ABS)
3705 fprintf (file, " ABSOLUTE");
3706 if (symtab && symtab->symbols
3707 && isym < symtab->nsyms
3708 && symtab->symbols[isym].symbol.name)
3709 fprintf (file, " %s", symtab->symbols[isym].symbol.name);
3710 fprintf (file, "\n");
afecc97c 3711 addr += entry_size;
046b007d
TG
3712 }
3713 break;
3714 default:
3715 break;
3716 }
3717 }
3718 }
3719 if (dysymtab->nextrefsyms > 0)
3720 {
3721 bfd_mach_o_symtab_command *symtab = mdata->symtab;
3722
3723 fprintf (file, " external reference table: (symbol flags)\n");
3724 for (i = 0; i < dysymtab->nextrefsyms; i++)
3725 {
3726 bfd_mach_o_dylib_reference *ref = &dysymtab->ext_refs[i];
3727
3728 fprintf (file, " %4u: %5lu 0x%02lx", i, ref->isym, ref->flags);
3729 if (symtab && symtab->symbols
3730 && ref->isym < symtab->nsyms
3731 && symtab->symbols[ref->isym].symbol.name)
3732 fprintf (file, " %s", symtab->symbols[ref->isym].symbol.name);
3733 fprintf (file, "\n");
3734 }
3735 }
3736
3737}
3738
ad86f1fb
TG
3739static void
3740bfd_mach_o_print_dyld_info (bfd *abfd ATTRIBUTE_UNUSED,
3741 bfd_mach_o_load_command *cmd, FILE *file)
3742{
3743 bfd_mach_o_dyld_info_command *info = &cmd->command.dyld_info;
3744
3745 fprintf (file, " rebase: off: 0x%08x size: %-8u\n",
3746 info->rebase_off, info->rebase_size);
3747 fprintf (file, " bind: off: 0x%08x size: %-8u\n",
3748 info->bind_off, info->bind_size);
3749 fprintf (file, " weak bind: off: 0x%08x size: %-8u\n",
3750 info->weak_bind_off, info->weak_bind_size);
3751 fprintf (file, " lazy bind: off: 0x%08x size: %-8u\n",
3752 info->lazy_bind_off, info->lazy_bind_size);
3753 fprintf (file, " export: off: 0x%08x size: %-8u\n",
3754 info->export_off, info->export_size);
3755}
3756
046b007d 3757bfd_boolean
91d6fa6a 3758bfd_mach_o_bfd_print_private_bfd_data (bfd *abfd, void * ptr)
046b007d
TG
3759{
3760 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3761 FILE *file = (FILE *) ptr;
3762 unsigned int i;
3763
3764 bfd_mach_o_print_private_header (abfd, file);
3765 fputc ('\n', file);
15e1c58a
TG
3766
3767 for (i = 0; i < mdata->header.ncmds; i++)
3768 {
3769 bfd_mach_o_load_command *cmd = &mdata->commands[i];
046b007d
TG
3770
3771 fprintf (file, "Load command %s:",
3772 bfd_mach_o_get_name (bfd_mach_o_load_command_name, cmd->type));
15e1c58a
TG
3773 switch (cmd->type)
3774 {
3775 case BFD_MACH_O_LC_SEGMENT:
3776 case BFD_MACH_O_LC_SEGMENT_64:
046b007d 3777 bfd_mach_o_print_segment (abfd, cmd, file);
15e1c58a
TG
3778 break;
3779 case BFD_MACH_O_LC_UUID:
3780 {
3781 bfd_mach_o_uuid_command *uuid = &cmd->command.uuid;
91d6fa6a 3782 unsigned int j;
15e1c58a 3783
91d6fa6a
NC
3784 for (j = 0; j < sizeof (uuid->uuid); j ++)
3785 fprintf (file, " %02x", uuid->uuid[j]);
15e1c58a
TG
3786 fputc ('\n', file);
3787 }
3788 break;
3789 case BFD_MACH_O_LC_LOAD_DYLIB:
046b007d
TG
3790 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
3791 case BFD_MACH_O_LC_REEXPORT_DYLIB:
3792 case BFD_MACH_O_LC_ID_DYLIB:
15e1c58a
TG
3793 {
3794 bfd_mach_o_dylib_command *dylib = &cmd->command.dylib;
b32e07d7 3795 fprintf (file, " %s\n", dylib->name_str);
15e1c58a
TG
3796 fprintf (file, " time stamp: 0x%08lx\n",
3797 dylib->timestamp);
3798 fprintf (file, " current version: 0x%08lx\n",
3799 dylib->current_version);
3800 fprintf (file, " comptibility version: 0x%08lx\n",
3801 dylib->compatibility_version);
15e1c58a
TG
3802 break;
3803 }
3804 case BFD_MACH_O_LC_LOAD_DYLINKER:
b32e07d7
TG
3805 case BFD_MACH_O_LC_ID_DYLINKER:
3806 fprintf (file, " %s\n", cmd->command.dylinker.name_str);
3807 break;
15e1c58a
TG
3808 case BFD_MACH_O_LC_SYMTAB:
3809 {
3810 bfd_mach_o_symtab_command *symtab = &cmd->command.symtab;
15e1c58a 3811 fprintf (file,
046b007d
TG
3812 "\n"
3813 " symoff: 0x%08x nsyms: %8u (endoff: 0x%08x)\n",
3814 symtab->symoff, symtab->nsyms,
3815 symtab->symoff + symtab->nsyms
3816 * (mach_o_wide_p (&mdata->header)
3817 ? BFD_MACH_O_NLIST_64_SIZE : BFD_MACH_O_NLIST_SIZE));
15e1c58a 3818 fprintf (file,
046b007d
TG
3819 " stroff: 0x%08x strsize: %8u (endoff: 0x%08x)\n",
3820 symtab->stroff, symtab->strsize,
3821 symtab->stroff + symtab->strsize);
15e1c58a
TG
3822 break;
3823 }
046b007d
TG
3824 case BFD_MACH_O_LC_DYSYMTAB:
3825 fprintf (file, "\n");
3826 bfd_mach_o_print_dysymtab (abfd, cmd, file);
3827 break;
3828 case BFD_MACH_O_LC_CODE_SIGNATURE:
3829 case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO:
3830 {
3831 bfd_mach_o_linkedit_command *linkedit = &cmd->command.linkedit;
3832 fprintf
3833 (file, "\n"
3834 " dataoff: 0x%08lx datasize: 0x%08lx (endoff: 0x%08lx)\n",
3835 linkedit->dataoff, linkedit->datasize,
3836 linkedit->dataoff + linkedit->datasize);
3837 break;
3838 }
3839 case BFD_MACH_O_LC_SUB_FRAMEWORK:
3840 case BFD_MACH_O_LC_SUB_UMBRELLA:
3841 case BFD_MACH_O_LC_SUB_LIBRARY:
3842 case BFD_MACH_O_LC_SUB_CLIENT:
0c9b2b4c 3843 case BFD_MACH_O_LC_RPATH:
046b007d
TG
3844 {
3845 bfd_mach_o_str_command *str = &cmd->command.str;
3846 fprintf (file, " %s\n", str->str);
3847 break;
3848 }
b32e07d7
TG
3849 case BFD_MACH_O_LC_THREAD:
3850 case BFD_MACH_O_LC_UNIXTHREAD:
3851 {
3852 bfd_mach_o_thread_command *thread = &cmd->command.thread;
3853 unsigned int j;
3854 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
3855
3856 fprintf (file, " nflavours: %lu\n", thread->nflavours);
3857 for (j = 0; j < thread->nflavours; j++)
3858 {
3859 bfd_mach_o_thread_flavour *flavour = &thread->flavours[j];
3860
3861 fprintf (file, " %2u: flavour: 0x%08lx offset: 0x%08lx"
3862 " size: 0x%08lx\n",
3863 j, flavour->flavour, flavour->offset,
3864 flavour->size);
3865 if (bed->_bfd_mach_o_print_thread)
3866 {
3867 char *buf = bfd_malloc (flavour->size);
3868
3869 if (buf
3870 && bfd_seek (abfd, flavour->offset, SEEK_SET) == 0
3871 && (bfd_bread (buf, flavour->size, abfd)
3872 == flavour->size))
3873 (*bed->_bfd_mach_o_print_thread)(abfd, flavour,
3874 file, buf);
3875 free (buf);
3876 }
3877 }
3878 break;
3879 }
ad86f1fb
TG
3880 case BFD_MACH_O_LC_DYLD_INFO:
3881 fprintf (file, "\n");
3882 bfd_mach_o_print_dyld_info (abfd, cmd, file);
3883 break;
15e1c58a 3884 default:
046b007d 3885 fprintf (file, "\n");
15e1c58a
TG
3886 break;
3887 }
046b007d 3888 fputc ('\n', file);
15e1c58a
TG
3889 }
3890
046b007d
TG
3891 bfd_mach_o_print_section_map (abfd, file);
3892
15e1c58a
TG
3893 return TRUE;
3894}
3895
3af9a47b 3896int
116c20d2
NC
3897bfd_mach_o_core_fetch_environment (bfd *abfd,
3898 unsigned char **rbuf,
3899 unsigned int *rlen)
3af9a47b 3900{
046b007d 3901 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b
NC
3902 unsigned long stackaddr = bfd_mach_o_stack_addr (mdata->header.cputype);
3903 unsigned int i = 0;
3904
3905 for (i = 0; i < mdata->header.ncmds; i++)
3906 {
3907 bfd_mach_o_load_command *cur = &mdata->commands[i];
3908 bfd_mach_o_segment_command *seg = NULL;
3909
3910 if (cur->type != BFD_MACH_O_LC_SEGMENT)
3911 continue;
3912
3913 seg = &cur->command.segment;
3914
3915 if ((seg->vmaddr + seg->vmsize) == stackaddr)
3916 {
3917 unsigned long start = seg->fileoff;
3918 unsigned long end = seg->fileoff + seg->filesize;
3919 unsigned char *buf = bfd_malloc (1024);
3920 unsigned long size = 1024;
3921
3922 for (;;)
3923 {
3924 bfd_size_type nread = 0;
3925 unsigned long offset;
3926 int found_nonnull = 0;
3927
3928 if (size > (end - start))
3929 size = (end - start);
3930
515ef31d
NC
3931 buf = bfd_realloc_or_free (buf, size);
3932 if (buf == NULL)
3933 return -1;
c2f09c75
TG
3934
3935 if (bfd_seek (abfd, end - size, SEEK_SET) != 0)
3936 {
3937 free (buf);
3938 return -1;
3939 }
3940
3af9a47b 3941 nread = bfd_bread (buf, size, abfd);
a95a4550 3942
3af9a47b 3943 if (nread != size)
515ef31d
NC
3944 {
3945 free (buf);
3946 return -1;
3947 }
a95a4550 3948
3af9a47b
NC
3949 for (offset = 4; offset <= size; offset += 4)
3950 {
e84d6fca 3951 unsigned long val;
3af9a47b 3952
e84d6fca 3953 val = *((unsigned long *) (buf + size - offset));
3af9a47b
NC
3954 if (! found_nonnull)
3955 {
3956 if (val != 0)
3957 found_nonnull = 1;
3958 }
3959 else if (val == 0x0)
3960 {
e84d6fca
AM
3961 unsigned long bottom;
3962 unsigned long top;
3af9a47b 3963
e84d6fca
AM
3964 bottom = seg->fileoff + seg->filesize - offset;
3965 top = seg->fileoff + seg->filesize - 4;
3af9a47b
NC
3966 *rbuf = bfd_malloc (top - bottom);
3967 *rlen = top - bottom;
3968
3969 memcpy (*rbuf, buf + size - *rlen, *rlen);
515ef31d 3970 free (buf);
3af9a47b
NC
3971 return 0;
3972 }
3973 }
3974
3975 if (size == (end - start))
3976 break;
3977
3978 size *= 2;
3979 }
515ef31d
NC
3980
3981 free (buf);
3af9a47b
NC
3982 }
3983 }
3984
3985 return -1;
3986}
3987
3988char *
116c20d2 3989bfd_mach_o_core_file_failing_command (bfd *abfd)
3af9a47b
NC
3990{
3991 unsigned char *buf = NULL;
3992 unsigned int len = 0;
3993 int ret = -1;
3994
3995 ret = bfd_mach_o_core_fetch_environment (abfd, &buf, &len);
3996 if (ret < 0)
3997 return NULL;
3998
f075ee0c 3999 return (char *) buf;
3af9a47b
NC
4000}
4001
4002int
116c20d2 4003bfd_mach_o_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
3af9a47b
NC
4004{
4005 return 0;
4006}
4007
92bc0e80
TG
4008#define bfd_mach_o_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
4009#define bfd_mach_o_bfd_reloc_name_lookup _bfd_norelocs_bfd_reloc_name_lookup
4010
4011#define bfd_mach_o_swap_reloc_in NULL
4012#define bfd_mach_o_swap_reloc_out NULL
b32e07d7 4013#define bfd_mach_o_print_thread NULL
92bc0e80 4014
116c20d2
NC
4015#define TARGET_NAME mach_o_be_vec
4016#define TARGET_STRING "mach-o-be"
42fa0891 4017#define TARGET_ARCHITECTURE bfd_arch_unknown
116c20d2
NC
4018#define TARGET_BIG_ENDIAN 1
4019#define TARGET_ARCHIVE 0
3af9a47b
NC
4020#include "mach-o-target.c"
4021
4022#undef TARGET_NAME
4023#undef TARGET_STRING
42fa0891 4024#undef TARGET_ARCHITECTURE
3af9a47b
NC
4025#undef TARGET_BIG_ENDIAN
4026#undef TARGET_ARCHIVE
4027
116c20d2
NC
4028#define TARGET_NAME mach_o_le_vec
4029#define TARGET_STRING "mach-o-le"
42fa0891 4030#define TARGET_ARCHITECTURE bfd_arch_unknown
116c20d2
NC
4031#define TARGET_BIG_ENDIAN 0
4032#define TARGET_ARCHIVE 0
3af9a47b
NC
4033
4034#include "mach-o-target.c"
4035
4036#undef TARGET_NAME
4037#undef TARGET_STRING
42fa0891 4038#undef TARGET_ARCHITECTURE
3af9a47b
NC
4039#undef TARGET_BIG_ENDIAN
4040#undef TARGET_ARCHIVE
4041
8f95b6e4
TG
4042/* Not yet handled: creating an archive. */
4043#define bfd_mach_o_mkarchive _bfd_noarchive_mkarchive
4044
4045/* Not used. */
4046#define bfd_mach_o_read_ar_hdr _bfd_noarchive_read_ar_hdr
4047#define bfd_mach_o_write_ar_hdr _bfd_noarchive_write_ar_hdr
4048#define bfd_mach_o_slurp_armap _bfd_noarchive_slurp_armap
4049#define bfd_mach_o_slurp_extended_name_table _bfd_noarchive_slurp_extended_name_table
4050#define bfd_mach_o_construct_extended_name_table _bfd_noarchive_construct_extended_name_table
4051#define bfd_mach_o_truncate_arname _bfd_noarchive_truncate_arname
4052#define bfd_mach_o_write_armap _bfd_noarchive_write_armap
4053#define bfd_mach_o_get_elt_at_index _bfd_noarchive_get_elt_at_index
4054#define bfd_mach_o_generic_stat_arch_elt _bfd_noarchive_generic_stat_arch_elt
4055#define bfd_mach_o_update_armap_timestamp _bfd_noarchive_update_armap_timestamp
4056
116c20d2
NC
4057#define TARGET_NAME mach_o_fat_vec
4058#define TARGET_STRING "mach-o-fat"
42fa0891 4059#define TARGET_ARCHITECTURE bfd_arch_unknown
116c20d2
NC
4060#define TARGET_BIG_ENDIAN 1
4061#define TARGET_ARCHIVE 1
3af9a47b
NC
4062
4063#include "mach-o-target.c"
4064
4065#undef TARGET_NAME
4066#undef TARGET_STRING
42fa0891 4067#undef TARGET_ARCHITECTURE
3af9a47b
NC
4068#undef TARGET_BIG_ENDIAN
4069#undef TARGET_ARCHIVE
This page took 0.668653 seconds and 4 git commands to generate.