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