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