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