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