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