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