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