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