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