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