daily update
[deliverable/binutils-gdb.git] / bfd / mach-o.c
CommitLineData
3af9a47b 1/* Mach-O support for BFD.
4f608e79 2 Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
4a97a0e5 3 2009, 2010, 2011
3af9a47b
NC
4 Free Software Foundation, Inc.
5
6 This file is part of BFD, the Binary File Descriptor library.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
cd123cb7 10 the Free Software Foundation; either version 3 of the License, or
3af9a47b
NC
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a95a4550 19 along with this program; if not, write to the Free Software
cd123cb7
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
3af9a47b 22
3db64b00 23#include "sysdep.h"
3af9a47b
NC
24#include "mach-o.h"
25#include "bfd.h"
3af9a47b
NC
26#include "libbfd.h"
27#include "libiberty.h"
15e1c58a 28#include "aout/stab_gnu.h"
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 {
4a97a0e5 381 (*_bfd_error_handler) (_("bfd_mach_o_canonicalize_symtab: unable to load symbols"));
046b007d
TG
382 return 0;
383 }
3af9a47b 384
046b007d 385 BFD_ASSERT (sym->symbols != NULL);
3af9a47b 386
046b007d
TG
387 for (j = 0; j < sym->nsyms; j++)
388 alocation[j] = &sym->symbols[j].symbol;
3af9a47b 389
046b007d 390 alocation[j] = NULL;
a95a4550 391
3af9a47b
NC
392 return nsyms;
393}
394
b2b62060
TG
395long
396bfd_mach_o_get_synthetic_symtab (bfd *abfd,
397 long symcount ATTRIBUTE_UNUSED,
398 asymbol **syms ATTRIBUTE_UNUSED,
399 long dynsymcount ATTRIBUTE_UNUSED,
400 asymbol **dynsyms ATTRIBUTE_UNUSED,
401 asymbol **ret)
402{
403 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
404 bfd_mach_o_dysymtab_command *dysymtab = mdata->dysymtab;
405 bfd_mach_o_symtab_command *symtab = mdata->symtab;
406 asymbol *s;
407 unsigned long count, i, j, n;
408 size_t size;
409 char *names;
410 char *nul_name;
411
412 *ret = NULL;
413
414 if (dysymtab == NULL || symtab == NULL || symtab->symbols == NULL)
415 return 0;
416
417 if (dysymtab->nindirectsyms == 0)
418 return 0;
419
420 count = dysymtab->nindirectsyms;
421 size = count * sizeof (asymbol) + 1;
422
423 for (j = 0; j < count; j++)
424 {
425 unsigned int isym = dysymtab->indirect_syms[j];
426
427 if (isym < symtab->nsyms && symtab->symbols[isym].symbol.name)
428 size += strlen (symtab->symbols[isym].symbol.name) + sizeof ("$stub");
429 }
430
431 s = *ret = (asymbol *) bfd_malloc (size);
432 if (s == NULL)
433 return -1;
434 names = (char *) (s + count);
435 nul_name = names;
436 *names++ = 0;
437
438 n = 0;
439 for (i = 0; i < mdata->nsects; i++)
440 {
441 bfd_mach_o_section *sec = mdata->sections[i];
91d6fa6a 442 unsigned int first, last;
b2b62060
TG
443 bfd_vma addr;
444 bfd_vma entry_size;
445
446 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
447 {
448 case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
449 case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
450 case BFD_MACH_O_S_SYMBOL_STUBS:
451 first = sec->reserved1;
452 last = first + bfd_mach_o_section_get_nbr_indirect (abfd, sec);
453 addr = sec->addr;
454 entry_size = bfd_mach_o_section_get_entry_size (abfd, sec);
455 for (j = first; j < last; j++)
456 {
457 unsigned int isym = dysymtab->indirect_syms[j];
458
459 s->flags = BSF_GLOBAL | BSF_SYNTHETIC;
460 s->section = sec->bfdsection;
461 s->value = addr - sec->addr;
462 s->udata.p = NULL;
463
464 if (isym < symtab->nsyms
465 && symtab->symbols[isym].symbol.name)
466 {
467 const char *sym = symtab->symbols[isym].symbol.name;
468 size_t len;
469
470 s->name = names;
471 len = strlen (sym);
472 memcpy (names, sym, len);
473 names += len;
474 memcpy (names, "$stub", sizeof ("$stub"));
475 names += sizeof ("$stub");
476 }
477 else
478 s->name = nul_name;
479
480 addr += entry_size;
481 s++;
482 n++;
483 }
484 break;
485 default:
486 break;
487 }
488 }
489
490 return n;
491}
492
154a1ee5 493void
116c20d2
NC
494bfd_mach_o_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
495 asymbol *symbol,
496 symbol_info *ret)
3af9a47b
NC
497{
498 bfd_symbol_info (symbol, ret);
499}
500
154a1ee5 501void
116c20d2 502bfd_mach_o_print_symbol (bfd *abfd,
91d6fa6a 503 void * afile,
116c20d2
NC
504 asymbol *symbol,
505 bfd_print_symbol_type how)
3af9a47b
NC
506{
507 FILE *file = (FILE *) afile;
15e1c58a 508 const char *name;
92bc0e80 509 bfd_mach_o_asymbol *asym = (bfd_mach_o_asymbol *)symbol;
3af9a47b
NC
510
511 switch (how)
512 {
513 case bfd_print_symbol_name:
514 fprintf (file, "%s", symbol->name);
515 break;
516 default:
91d6fa6a 517 bfd_print_symbol_vandf (abfd, (void *) file, symbol);
92bc0e80
TG
518 if (asym->n_type & BFD_MACH_O_N_STAB)
519 name = bfd_get_stab_name (asym->n_type);
15e1c58a 520 else
92bc0e80 521 switch (asym->n_type & BFD_MACH_O_N_TYPE)
15e1c58a
TG
522 {
523 case BFD_MACH_O_N_UNDF:
524 name = "UND";
525 break;
526 case BFD_MACH_O_N_ABS:
527 name = "ABS";
528 break;
529 case BFD_MACH_O_N_INDR:
530 name = "INDR";
531 break;
532 case BFD_MACH_O_N_PBUD:
533 name = "PBUD";
534 break;
535 case BFD_MACH_O_N_SECT:
536 name = "SECT";
537 break;
538 default:
539 name = "???";
540 break;
541 }
542 if (name == NULL)
543 name = "";
92bc0e80
TG
544 fprintf (file, " %02x %-6s %02x %04x",
545 asym->n_type, name, asym->n_sect, asym->n_desc);
546 if ((asym->n_type & BFD_MACH_O_N_STAB) == 0
547 && (asym->n_type & BFD_MACH_O_N_TYPE) == BFD_MACH_O_N_SECT)
15e1c58a
TG
548 fprintf (file, " %-5s", symbol->section->name);
549 fprintf (file, " %s", symbol->name);
3af9a47b
NC
550 }
551}
552
553static void
116c20d2
NC
554bfd_mach_o_convert_architecture (bfd_mach_o_cpu_type mtype,
555 bfd_mach_o_cpu_subtype msubtype ATTRIBUTE_UNUSED,
556 enum bfd_architecture *type,
557 unsigned long *subtype)
3af9a47b
NC
558{
559 *subtype = bfd_arch_unknown;
560
561 switch (mtype)
562 {
563 case BFD_MACH_O_CPU_TYPE_VAX: *type = bfd_arch_vax; break;
564 case BFD_MACH_O_CPU_TYPE_MC680x0: *type = bfd_arch_m68k; break;
1e8a024a
TG
565 case BFD_MACH_O_CPU_TYPE_I386:
566 *type = bfd_arch_i386;
567 *subtype = bfd_mach_i386_i386;
568 break;
569 case BFD_MACH_O_CPU_TYPE_X86_64:
570 *type = bfd_arch_i386;
571 *subtype = bfd_mach_x86_64;
572 break;
3af9a47b
NC
573 case BFD_MACH_O_CPU_TYPE_MIPS: *type = bfd_arch_mips; break;
574 case BFD_MACH_O_CPU_TYPE_MC98000: *type = bfd_arch_m98k; break;
575 case BFD_MACH_O_CPU_TYPE_HPPA: *type = bfd_arch_hppa; break;
576 case BFD_MACH_O_CPU_TYPE_ARM: *type = bfd_arch_arm; break;
577 case BFD_MACH_O_CPU_TYPE_MC88000: *type = bfd_arch_m88k; break;
1e8a024a
TG
578 case BFD_MACH_O_CPU_TYPE_SPARC:
579 *type = bfd_arch_sparc;
580 *subtype = bfd_mach_sparc;
581 break;
3af9a47b
NC
582 case BFD_MACH_O_CPU_TYPE_I860: *type = bfd_arch_i860; break;
583 case BFD_MACH_O_CPU_TYPE_ALPHA: *type = bfd_arch_alpha; break;
1e8a024a
TG
584 case BFD_MACH_O_CPU_TYPE_POWERPC:
585 *type = bfd_arch_powerpc;
c2f09c75 586 *subtype = bfd_mach_ppc;
1e8a024a
TG
587 break;
588 case BFD_MACH_O_CPU_TYPE_POWERPC_64:
589 *type = bfd_arch_powerpc;
c2f09c75 590 *subtype = bfd_mach_ppc64;
1e8a024a 591 break;
3af9a47b 592 default:
1e8a024a
TG
593 *type = bfd_arch_unknown;
594 break;
3af9a47b
NC
595 }
596}
a95a4550 597
154a1ee5 598static bfd_boolean
116c20d2
NC
599bfd_mach_o_write_header (bfd *abfd, bfd_mach_o_header *header)
600{
1e8a024a
TG
601 unsigned char buf[32];
602 unsigned int size;
603
c2f09c75 604 size = mach_o_wide_p (header) ?
154a1ee5 605 BFD_MACH_O_HEADER_64_SIZE : BFD_MACH_O_HEADER_SIZE;
116c20d2
NC
606
607 bfd_h_put_32 (abfd, header->magic, buf + 0);
608 bfd_h_put_32 (abfd, header->cputype, buf + 4);
609 bfd_h_put_32 (abfd, header->cpusubtype, buf + 8);
610 bfd_h_put_32 (abfd, header->filetype, buf + 12);
611 bfd_h_put_32 (abfd, header->ncmds, buf + 16);
612 bfd_h_put_32 (abfd, header->sizeofcmds, buf + 20);
613 bfd_h_put_32 (abfd, header->flags, buf + 24);
614
c2f09c75 615 if (mach_o_wide_p (header))
1e8a024a
TG
616 bfd_h_put_32 (abfd, header->reserved, buf + 28);
617
c2f09c75 618 if (bfd_seek (abfd, 0, SEEK_SET) != 0
91d6fa6a 619 || bfd_bwrite ((void *) buf, size, abfd) != size)
154a1ee5 620 return FALSE;
116c20d2 621
154a1ee5 622 return TRUE;
116c20d2
NC
623}
624
625static int
ab273af8 626bfd_mach_o_write_thread (bfd *abfd, bfd_mach_o_load_command *command)
116c20d2
NC
627{
628 bfd_mach_o_thread_command *cmd = &command->command.thread;
629 unsigned int i;
630 unsigned char buf[8];
92bc0e80 631 unsigned int offset;
116c20d2
NC
632
633 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
634 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
635
636 offset = 8;
116c20d2
NC
637 for (i = 0; i < cmd->nflavours; i++)
638 {
639 BFD_ASSERT ((cmd->flavours[i].size % 4) == 0);
640 BFD_ASSERT (cmd->flavours[i].offset == (command->offset + offset + 8));
641
642 bfd_h_put_32 (abfd, cmd->flavours[i].flavour, buf);
643 bfd_h_put_32 (abfd, (cmd->flavours[i].size / 4), buf + 4);
644
c2f09c75 645 if (bfd_seek (abfd, command->offset + offset, SEEK_SET) != 0
91d6fa6a 646 || bfd_bwrite ((void *) buf, 8, abfd) != 8)
116c20d2
NC
647 return -1;
648
649 offset += cmd->flavours[i].size + 8;
650 }
651
652 return 0;
653}
654
92bc0e80
TG
655long
656bfd_mach_o_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
657 asection *asect)
658{
659 return (asect->reloc_count + 1) * sizeof (arelent *);
660}
661
b32e07d7
TG
662static int
663bfd_mach_o_canonicalize_one_reloc (bfd *abfd, char *buf,
664 arelent *res, asymbol **syms)
92bc0e80 665{
046b007d 666 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
92bc0e80 667 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
b32e07d7
TG
668 bfd_mach_o_reloc_info reloc;
669 bfd_vma addr;
670 bfd_vma symnum;
671 asymbol **sym;
672
673 addr = bfd_get_32 (abfd, buf + 0);
674 symnum = bfd_get_32 (abfd, buf + 4);
675
676 if (addr & BFD_MACH_O_SR_SCATTERED)
677 {
678 unsigned int j;
679
680 /* Scattered relocation.
681 Extract section and offset from r_value. */
682 res->sym_ptr_ptr = NULL;
683 res->addend = 0;
684 for (j = 0; j < mdata->nsects; j++)
685 {
686 bfd_mach_o_section *sect = mdata->sections[j];
687 if (symnum >= sect->addr && symnum < sect->addr + sect->size)
688 {
689 res->sym_ptr_ptr = sect->bfdsection->symbol_ptr_ptr;
690 res->addend = symnum - sect->addr;
691 break;
692 }
693 }
694 res->address = BFD_MACH_O_GET_SR_ADDRESS (addr);
695 reloc.r_type = BFD_MACH_O_GET_SR_TYPE (addr);
696 reloc.r_length = BFD_MACH_O_GET_SR_LENGTH (addr);
697 reloc.r_pcrel = addr & BFD_MACH_O_SR_PCREL;
698 reloc.r_scattered = 1;
699 }
700 else
701 {
702 unsigned int num = BFD_MACH_O_GET_R_SYMBOLNUM (symnum);
703 res->addend = 0;
704 res->address = addr;
705 if (symnum & BFD_MACH_O_R_EXTERN)
06988dfc
TG
706 {
707 sym = syms + num;
708 reloc.r_extern = 1;
709 }
b32e07d7
TG
710 else
711 {
712 BFD_ASSERT (num != 0);
713 BFD_ASSERT (num <= mdata->nsects);
714 sym = mdata->sections[num - 1]->bfdsection->symbol_ptr_ptr;
1523fa24
TG
715 /* For a symbol defined in section S, the addend (stored in the
716 binary) contains the address of the section. To comply with
717 bfd conventio, substract the section address.
718 Use the address from the header, so that the user can modify
719 the vma of the section. */
720 res->addend = -mdata->sections[num - 1]->addr;
06988dfc 721 reloc.r_extern = 0;
b32e07d7
TG
722 }
723 res->sym_ptr_ptr = sym;
724 reloc.r_type = BFD_MACH_O_GET_R_TYPE (symnum);
725 reloc.r_length = BFD_MACH_O_GET_R_LENGTH (symnum);
726 reloc.r_pcrel = (symnum & BFD_MACH_O_R_PCREL) ? 1 : 0;
727 reloc.r_scattered = 0;
728 }
729
730 if (!(*bed->_bfd_mach_o_swap_reloc_in)(res, &reloc))
731 return -1;
732 return 0;
733}
734
735static int
736bfd_mach_o_canonicalize_relocs (bfd *abfd, unsigned long filepos,
737 unsigned long count,
738 arelent *res, asymbol **syms)
739{
92bc0e80 740 unsigned long i;
92bc0e80
TG
741 char *native_relocs;
742 bfd_size_type native_size;
743
92bc0e80 744 /* Allocate and read relocs. */
b32e07d7 745 native_size = count * BFD_MACH_O_RELENT_SIZE;
92bc0e80
TG
746 native_relocs = bfd_malloc (native_size);
747 if (native_relocs == NULL)
748 return -1;
749
b32e07d7 750 if (bfd_seek (abfd, filepos, SEEK_SET) != 0
92bc0e80 751 || bfd_bread (native_relocs, native_size, abfd) != native_size)
b32e07d7
TG
752 goto err;
753
754 for (i = 0; i < count; i++)
92bc0e80 755 {
b32e07d7
TG
756 char *buf = native_relocs + BFD_MACH_O_RELENT_SIZE * i;
757
758 if (bfd_mach_o_canonicalize_one_reloc (abfd, buf, &res[i], syms) < 0)
759 goto err;
92bc0e80 760 }
b32e07d7
TG
761 free (native_relocs);
762 return i;
763 err:
764 free (native_relocs);
765 return -1;
766}
767
768long
769bfd_mach_o_canonicalize_reloc (bfd *abfd, asection *asect,
770 arelent **rels, asymbol **syms)
771{
772 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
773 unsigned long i;
774 arelent *res;
775
776 if (asect->reloc_count == 0)
777 return 0;
778
779 /* No need to go further if we don't know how to read relocs. */
780 if (bed->_bfd_mach_o_swap_reloc_in == NULL)
781 return 0;
92bc0e80
TG
782
783 res = bfd_malloc (asect->reloc_count * sizeof (arelent));
784 if (res == NULL)
b32e07d7
TG
785 return -1;
786
787 if (bfd_mach_o_canonicalize_relocs (abfd, asect->rel_filepos,
788 asect->reloc_count, res, syms) < 0)
92bc0e80 789 {
b32e07d7 790 free (res);
92bc0e80
TG
791 return -1;
792 }
793
794 for (i = 0; i < asect->reloc_count; i++)
b32e07d7
TG
795 rels[i] = &res[i];
796 rels[i] = NULL;
797 asect->relocation = res;
92bc0e80 798
b32e07d7
TG
799 return i;
800}
92bc0e80 801
b32e07d7
TG
802long
803bfd_mach_o_get_dynamic_reloc_upper_bound (bfd *abfd)
804{
805 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
92bc0e80 806
b32e07d7
TG
807 if (mdata->dysymtab == NULL)
808 return 1;
809 return (mdata->dysymtab->nextrel + mdata->dysymtab->nlocrel)
810 * sizeof (arelent *);
811}
92bc0e80 812
b32e07d7
TG
813long
814bfd_mach_o_canonicalize_dynamic_reloc (bfd *abfd, arelent **rels,
815 struct bfd_symbol **syms)
816{
817 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
818 bfd_mach_o_dysymtab_command *dysymtab = mdata->dysymtab;
819 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
820 unsigned long i;
821 arelent *res;
822
823 if (dysymtab == NULL)
824 return 0;
825 if (dysymtab->nextrel == 0 && dysymtab->nlocrel == 0)
826 return 0;
827
828 /* No need to go further if we don't know how to read relocs. */
829 if (bed->_bfd_mach_o_swap_reloc_in == NULL)
830 return 0;
831
832 res = bfd_malloc ((dysymtab->nextrel + dysymtab->nlocrel) * sizeof (arelent));
833 if (res == NULL)
834 return -1;
835
836 if (bfd_mach_o_canonicalize_relocs (abfd, dysymtab->extreloff,
837 dysymtab->nextrel, res, syms) < 0)
838 {
839 free (res);
840 return -1;
92bc0e80 841 }
b32e07d7
TG
842
843 if (bfd_mach_o_canonicalize_relocs (abfd, dysymtab->locreloff,
844 dysymtab->nlocrel,
845 res + dysymtab->nextrel, syms) < 0)
846 {
847 free (res);
848 return -1;
849 }
850
851 for (i = 0; i < dysymtab->nextrel + dysymtab->nlocrel; i++)
852 rels[i] = &res[i];
853 rels[i] = NULL;
92bc0e80
TG
854 return i;
855}
856
857static bfd_boolean
ab273af8 858bfd_mach_o_write_relocs (bfd *abfd, bfd_mach_o_section *section)
92bc0e80 859{
046b007d 860 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
92bc0e80
TG
861 unsigned int i;
862 arelent **entries;
863 asection *sec;
864 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
865
866 sec = section->bfdsection;
867 if (sec->reloc_count == 0)
868 return TRUE;
869
870 if (bed->_bfd_mach_o_swap_reloc_out == NULL)
871 return TRUE;
872
873 /* Allocate relocation room. */
874 mdata->filelen = FILE_ALIGN(mdata->filelen, 2);
875 section->nreloc = sec->reloc_count;
876 sec->rel_filepos = mdata->filelen;
877 section->reloff = sec->rel_filepos;
878 mdata->filelen += sec->reloc_count * BFD_MACH_O_RELENT_SIZE;
879
880 if (bfd_seek (abfd, section->reloff, SEEK_SET) != 0)
881 return FALSE;
882
883 /* Convert and write. */
884 entries = section->bfdsection->orelocation;
885 for (i = 0; i < section->nreloc; i++)
886 {
887 arelent *rel = entries[i];
888 char buf[8];
889 bfd_mach_o_reloc_info info, *pinfo = &info;
890
891 /* Convert relocation to an intermediate representation. */
892 if (!(*bed->_bfd_mach_o_swap_reloc_out) (rel, pinfo))
893 return FALSE;
894
895 /* Lower the relocation info. */
896 if (pinfo->r_scattered)
897 {
898 unsigned long v;
899
900 v = BFD_MACH_O_SR_SCATTERED
901 | (pinfo->r_pcrel ? BFD_MACH_O_SR_PCREL : 0)
902 | BFD_MACH_O_SET_SR_LENGTH(pinfo->r_length)
903 | BFD_MACH_O_SET_SR_TYPE(pinfo->r_type)
904 | BFD_MACH_O_SET_SR_ADDRESS(pinfo->r_address);
905 bfd_put_32 (abfd, v, buf);
906 bfd_put_32 (abfd, pinfo->r_value, buf + 4);
907 }
908 else
909 {
910 unsigned long v;
911
912 bfd_put_32 (abfd, pinfo->r_address, buf);
913 v = BFD_MACH_O_SET_R_SYMBOLNUM (pinfo->r_value)
914 | (pinfo->r_pcrel ? BFD_MACH_O_R_PCREL : 0)
915 | BFD_MACH_O_SET_R_LENGTH (pinfo->r_length)
916 | (pinfo->r_extern ? BFD_MACH_O_R_EXTERN : 0)
917 | BFD_MACH_O_SET_R_TYPE (pinfo->r_type);
918 bfd_put_32 (abfd, v, buf + 4);
919 }
920
91d6fa6a 921 if (bfd_bwrite ((void *) buf, BFD_MACH_O_RELENT_SIZE, abfd)
92bc0e80
TG
922 != BFD_MACH_O_RELENT_SIZE)
923 return FALSE;
924 }
925 return TRUE;
926}
927
116c20d2 928static int
ab273af8 929bfd_mach_o_write_section_32 (bfd *abfd, bfd_mach_o_section *section)
116c20d2 930{
154a1ee5 931 unsigned char buf[BFD_MACH_O_SECTION_SIZE];
116c20d2
NC
932
933 memcpy (buf, section->sectname, 16);
934 memcpy (buf + 16, section->segname, 16);
935 bfd_h_put_32 (abfd, section->addr, buf + 32);
936 bfd_h_put_32 (abfd, section->size, buf + 36);
937 bfd_h_put_32 (abfd, section->offset, buf + 40);
938 bfd_h_put_32 (abfd, section->align, buf + 44);
939 bfd_h_put_32 (abfd, section->reloff, buf + 48);
940 bfd_h_put_32 (abfd, section->nreloc, buf + 52);
941 bfd_h_put_32 (abfd, section->flags, buf + 56);
1e8a024a
TG
942 bfd_h_put_32 (abfd, section->reserved1, buf + 60);
943 bfd_h_put_32 (abfd, section->reserved2, buf + 64);
116c20d2 944
91d6fa6a 945 if (bfd_bwrite ((void *) buf, BFD_MACH_O_SECTION_SIZE, abfd)
92bc0e80 946 != BFD_MACH_O_SECTION_SIZE)
116c20d2
NC
947 return -1;
948
949 return 0;
950}
951
952static int
ab273af8 953bfd_mach_o_write_section_64 (bfd *abfd, bfd_mach_o_section *section)
116c20d2 954{
154a1ee5 955 unsigned char buf[BFD_MACH_O_SECTION_64_SIZE];
116c20d2 956
1e8a024a
TG
957 memcpy (buf, section->sectname, 16);
958 memcpy (buf + 16, section->segname, 16);
959 bfd_h_put_64 (abfd, section->addr, buf + 32);
960 bfd_h_put_64 (abfd, section->size, buf + 40);
961 bfd_h_put_32 (abfd, section->offset, buf + 48);
962 bfd_h_put_32 (abfd, section->align, buf + 52);
963 bfd_h_put_32 (abfd, section->reloff, buf + 56);
964 bfd_h_put_32 (abfd, section->nreloc, buf + 60);
965 bfd_h_put_32 (abfd, section->flags, buf + 64);
966 bfd_h_put_32 (abfd, section->reserved1, buf + 68);
967 bfd_h_put_32 (abfd, section->reserved2, buf + 72);
968 bfd_h_put_32 (abfd, section->reserved3, buf + 76);
116c20d2 969
91d6fa6a 970 if (bfd_bwrite ((void *) buf, BFD_MACH_O_SECTION_64_SIZE, abfd)
92bc0e80 971 != BFD_MACH_O_SECTION_64_SIZE)
116c20d2
NC
972 return -1;
973
1e8a024a
TG
974 return 0;
975}
976
977static int
ab273af8 978bfd_mach_o_write_segment_32 (bfd *abfd, bfd_mach_o_load_command *command)
1e8a024a 979{
c2f09c75 980 unsigned char buf[BFD_MACH_O_LC_SEGMENT_SIZE];
1e8a024a
TG
981 bfd_mach_o_segment_command *seg = &command->command.segment;
982 unsigned long i;
983
c2f09c75
TG
984 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
985
92bc0e80 986 for (i = 0; i < seg->nsects; i++)
ab273af8 987 if (!bfd_mach_o_write_relocs (abfd, &seg->sections[i]))
92bc0e80 988 return -1;
c2f09c75 989
92bc0e80 990 memcpy (buf, seg->segname, 16);
c2f09c75
TG
991 bfd_h_put_32 (abfd, seg->vmaddr, buf + 16);
992 bfd_h_put_32 (abfd, seg->vmsize, buf + 20);
993 bfd_h_put_32 (abfd, seg->fileoff, buf + 24);
994 bfd_h_put_32 (abfd, seg->filesize, buf + 28);
995 bfd_h_put_32 (abfd, seg->maxprot, buf + 32);
996 bfd_h_put_32 (abfd, seg->initprot, buf + 36);
997 bfd_h_put_32 (abfd, seg->nsects, buf + 40);
998 bfd_h_put_32 (abfd, seg->flags, buf + 44);
999
1000 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 1001 || (bfd_bwrite ((void *) buf, BFD_MACH_O_LC_SEGMENT_SIZE - 8, abfd)
92bc0e80 1002 != BFD_MACH_O_LC_SEGMENT_SIZE - 8))
c2f09c75 1003 return -1;
1e8a024a 1004
116c20d2 1005 for (i = 0; i < seg->nsects; i++)
ab273af8 1006 if (bfd_mach_o_write_section_32 (abfd, &seg->sections[i]))
92bc0e80 1007 return -1;
1e8a024a 1008
116c20d2
NC
1009 return 0;
1010}
1011
1e8a024a 1012static int
ab273af8 1013bfd_mach_o_write_segment_64 (bfd *abfd, bfd_mach_o_load_command *command)
1e8a024a 1014{
c2f09c75
TG
1015 unsigned char buf[BFD_MACH_O_LC_SEGMENT_64_SIZE];
1016 bfd_mach_o_segment_command *seg = &command->command.segment;
1017 unsigned long i;
1018
1019 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT_64);
1020
92bc0e80 1021 for (i = 0; i < seg->nsects; i++)
ab273af8 1022 if (!bfd_mach_o_write_relocs (abfd, &seg->sections[i]))
92bc0e80 1023 return -1;
c2f09c75 1024
92bc0e80 1025 memcpy (buf, seg->segname, 16);
c2f09c75
TG
1026 bfd_h_put_64 (abfd, seg->vmaddr, buf + 16);
1027 bfd_h_put_64 (abfd, seg->vmsize, buf + 24);
1028 bfd_h_put_64 (abfd, seg->fileoff, buf + 32);
1029 bfd_h_put_64 (abfd, seg->filesize, buf + 40);
1030 bfd_h_put_32 (abfd, seg->maxprot, buf + 48);
1031 bfd_h_put_32 (abfd, seg->initprot, buf + 52);
1032 bfd_h_put_32 (abfd, seg->nsects, buf + 56);
1033 bfd_h_put_32 (abfd, seg->flags, buf + 60);
1034
1035 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 1036 || (bfd_bwrite ((void *) buf, BFD_MACH_O_LC_SEGMENT_64_SIZE - 8, abfd)
92bc0e80 1037 != BFD_MACH_O_LC_SEGMENT_64_SIZE - 8))
c2f09c75
TG
1038 return -1;
1039
1040 for (i = 0; i < seg->nsects; i++)
ab273af8 1041 if (bfd_mach_o_write_section_64 (abfd, &seg->sections[i]))
92bc0e80 1042 return -1;
c2f09c75 1043
c2f09c75 1044 return 0;
1e8a024a
TG
1045}
1046
c2f09c75 1047static bfd_boolean
ab273af8 1048bfd_mach_o_write_symtab (bfd *abfd, bfd_mach_o_load_command *command)
116c20d2 1049{
046b007d 1050 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
116c20d2 1051 bfd_mach_o_symtab_command *sym = &command->command.symtab;
c2f09c75 1052 unsigned char buf[16];
116c20d2 1053 unsigned long i;
c2f09c75 1054 unsigned int wide = bfd_mach_o_wide_p (abfd);
046b007d 1055 unsigned int symlen = wide ? BFD_MACH_O_NLIST_64_SIZE : BFD_MACH_O_NLIST_SIZE;
c2f09c75
TG
1056 struct bfd_strtab_hash *strtab;
1057 asymbol **symbols = bfd_get_outsymbols (abfd);
1058
1059 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
1060
1061 /* Write the symbols first. */
92bc0e80
TG
1062 mdata->filelen = FILE_ALIGN(mdata->filelen, wide ? 3 : 2);
1063 sym->symoff = mdata->filelen;
c2f09c75
TG
1064 if (bfd_seek (abfd, sym->symoff, SEEK_SET) != 0)
1065 return FALSE;
1066
1067 sym->nsyms = bfd_get_symcount (abfd);
92bc0e80 1068 mdata->filelen += sym->nsyms * symlen;
c2f09c75
TG
1069
1070 strtab = _bfd_stringtab_init ();
1071 if (strtab == NULL)
1072 return FALSE;
116c20d2
NC
1073
1074 for (i = 0; i < sym->nsyms; i++)
1075 {
91d6fa6a 1076 bfd_size_type str_index;
92bc0e80 1077 bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i];
c2f09c75 1078
92bc0e80 1079 /* Compute name index. */
c2f09c75 1080 /* An index of 0 always means the empty string. */
92bc0e80 1081 if (s->symbol.name == 0 || s->symbol.name[0] == '\0')
91d6fa6a 1082 str_index = 0;
c2f09c75
TG
1083 else
1084 {
91d6fa6a
NC
1085 str_index = _bfd_stringtab_add (strtab, s->symbol.name, TRUE, FALSE);
1086 if (str_index == (bfd_size_type) -1)
c2f09c75
TG
1087 goto err;
1088 }
91d6fa6a 1089 bfd_h_put_32 (abfd, str_index, buf);
92bc0e80
TG
1090 bfd_h_put_8 (abfd, s->n_type, buf + 4);
1091 bfd_h_put_8 (abfd, s->n_sect, buf + 5);
1092 bfd_h_put_16 (abfd, s->n_desc, buf + 6);
c2f09c75 1093 if (wide)
92bc0e80 1094 bfd_h_put_64 (abfd, s->symbol.section->vma + s->symbol.value, buf + 8);
c2f09c75 1095 else
92bc0e80 1096 bfd_h_put_32 (abfd, s->symbol.section->vma + s->symbol.value, buf + 8);
116c20d2 1097
91d6fa6a 1098 if (bfd_bwrite ((void *) buf, symlen, abfd) != symlen)
c2f09c75 1099 goto err;
116c20d2 1100 }
c2f09c75 1101 sym->strsize = _bfd_stringtab_size (strtab);
92bc0e80
TG
1102 sym->stroff = mdata->filelen;
1103 mdata->filelen += sym->strsize;
116c20d2 1104
c2f09c75
TG
1105 if (_bfd_stringtab_emit (abfd, strtab) != TRUE)
1106 goto err;
1107 _bfd_stringtab_free (strtab);
116c20d2 1108
c2f09c75
TG
1109 /* The command. */
1110 bfd_h_put_32 (abfd, sym->symoff, buf);
1111 bfd_h_put_32 (abfd, sym->nsyms, buf + 4);
1112 bfd_h_put_32 (abfd, sym->stroff, buf + 8);
1113 bfd_h_put_32 (abfd, sym->strsize, buf + 12);
116c20d2 1114
c2f09c75 1115 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 1116 || bfd_bwrite ((void *) buf, 16, abfd) != 16)
c2f09c75 1117 return FALSE;
116c20d2 1118
c2f09c75 1119 return TRUE;
116c20d2 1120
c2f09c75
TG
1121 err:
1122 _bfd_stringtab_free (strtab);
1123 return FALSE;
116c20d2
NC
1124}
1125
92bc0e80
TG
1126/* Process the symbols and generate Mach-O specific fields.
1127 Number them. */
1128
1129static bfd_boolean
1130bfd_mach_o_mangle_symbols (bfd *abfd)
1131{
1132 unsigned long i;
1133 asymbol **symbols = bfd_get_outsymbols (abfd);
1134
1135 for (i = 0; i < bfd_get_symcount (abfd); i++)
1136 {
1137 bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i];
1138
1139 if (s->n_type == BFD_MACH_O_N_UNDF && !(s->symbol.flags & BSF_DEBUGGING))
1140 {
1141 /* As genuine Mach-O symbols type shouldn't be N_UNDF (undefined
1142 symbols should be N_UNDEF | N_EXT), we suppose the back-end
1143 values haven't been set. */
1144 if (s->symbol.section == bfd_abs_section_ptr)
1145 s->n_type = BFD_MACH_O_N_ABS;
1146 else if (s->symbol.section == bfd_und_section_ptr)
1147 {
1148 s->n_type = BFD_MACH_O_N_UNDF;
1149 if (s->symbol.flags & BSF_WEAK)
1150 s->n_desc |= BFD_MACH_O_N_WEAK_REF;
1151 }
1152 else if (s->symbol.section == bfd_com_section_ptr)
1153 s->n_type = BFD_MACH_O_N_UNDF | BFD_MACH_O_N_EXT;
1154 else
1155 s->n_type = BFD_MACH_O_N_SECT;
1156
1157 if (s->symbol.flags & BSF_GLOBAL)
1158 s->n_type |= BFD_MACH_O_N_EXT;
1159 }
1160
1161 /* Compute section index. */
1162 if (s->symbol.section != bfd_abs_section_ptr
1163 && s->symbol.section != bfd_und_section_ptr
1164 && s->symbol.section != bfd_com_section_ptr)
1165 s->n_sect = s->symbol.section->target_index;
1166
1167 /* Number symbols. */
1168 s->symbol.udata.i = i;
1169 }
1170 return TRUE;
1171}
1172
154a1ee5 1173bfd_boolean
116c20d2 1174bfd_mach_o_write_contents (bfd *abfd)
3af9a47b
NC
1175{
1176 unsigned int i;
046b007d 1177 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b 1178
92bc0e80
TG
1179 if (mdata->header.ncmds == 0)
1180 if (!bfd_mach_o_build_commands (abfd))
1181 return FALSE;
1182
3af9a47b 1183 /* Now write header information. */
c2f09c75
TG
1184 if (mdata->header.filetype == 0)
1185 {
1186 if (abfd->flags & EXEC_P)
1187 mdata->header.filetype = BFD_MACH_O_MH_EXECUTE;
1188 else if (abfd->flags & DYNAMIC)
1189 mdata->header.filetype = BFD_MACH_O_MH_DYLIB;
1190 else
1191 mdata->header.filetype = BFD_MACH_O_MH_OBJECT;
1192 }
154a1ee5 1193 if (!bfd_mach_o_write_header (abfd, &mdata->header))
b34976b6 1194 return FALSE;
3af9a47b 1195
92bc0e80
TG
1196 /* Assign a number to each symbols. */
1197 if (!bfd_mach_o_mangle_symbols (abfd))
1198 return FALSE;
1199
3af9a47b
NC
1200 for (i = 0; i < mdata->header.ncmds; i++)
1201 {
1202 unsigned char buf[8];
1203 bfd_mach_o_load_command *cur = &mdata->commands[i];
1204 unsigned long typeflag;
1205
154a1ee5 1206 typeflag = cur->type | (cur->type_required ? BFD_MACH_O_LC_REQ_DYLD : 0);
3af9a47b
NC
1207
1208 bfd_h_put_32 (abfd, typeflag, buf);
1209 bfd_h_put_32 (abfd, cur->len, buf + 4);
1210
c2f09c75 1211 if (bfd_seek (abfd, cur->offset, SEEK_SET) != 0
91d6fa6a 1212 || bfd_bwrite ((void *) buf, 8, abfd) != 8)
b34976b6 1213 return FALSE;
3af9a47b
NC
1214
1215 switch (cur->type)
1216 {
1217 case BFD_MACH_O_LC_SEGMENT:
ab273af8 1218 if (bfd_mach_o_write_segment_32 (abfd, cur) != 0)
1e8a024a
TG
1219 return FALSE;
1220 break;
1221 case BFD_MACH_O_LC_SEGMENT_64:
ab273af8 1222 if (bfd_mach_o_write_segment_64 (abfd, cur) != 0)
b34976b6 1223 return FALSE;
3af9a47b
NC
1224 break;
1225 case BFD_MACH_O_LC_SYMTAB:
ab273af8 1226 if (!bfd_mach_o_write_symtab (abfd, cur))
b34976b6 1227 return FALSE;
3af9a47b
NC
1228 break;
1229 case BFD_MACH_O_LC_SYMSEG:
1230 break;
1231 case BFD_MACH_O_LC_THREAD:
1232 case BFD_MACH_O_LC_UNIXTHREAD:
ab273af8 1233 if (bfd_mach_o_write_thread (abfd, cur) != 0)
b34976b6 1234 return FALSE;
3af9a47b
NC
1235 break;
1236 case BFD_MACH_O_LC_LOADFVMLIB:
1237 case BFD_MACH_O_LC_IDFVMLIB:
1238 case BFD_MACH_O_LC_IDENT:
1239 case BFD_MACH_O_LC_FVMFILE:
1240 case BFD_MACH_O_LC_PREPAGE:
1241 case BFD_MACH_O_LC_DYSYMTAB:
1242 case BFD_MACH_O_LC_LOAD_DYLIB:
1243 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
1244 case BFD_MACH_O_LC_ID_DYLIB:
046b007d 1245 case BFD_MACH_O_LC_REEXPORT_DYLIB:
3af9a47b
NC
1246 case BFD_MACH_O_LC_LOAD_DYLINKER:
1247 case BFD_MACH_O_LC_ID_DYLINKER:
1248 case BFD_MACH_O_LC_PREBOUND_DYLIB:
1249 case BFD_MACH_O_LC_ROUTINES:
1250 case BFD_MACH_O_LC_SUB_FRAMEWORK:
1251 break;
1252 default:
4a97a0e5
AM
1253 (*_bfd_error_handler) (_("unable to write unknown load command 0x%lx"),
1254 (unsigned long) cur->type);
b34976b6 1255 return FALSE;
3af9a47b
NC
1256 }
1257 }
1258
b34976b6 1259 return TRUE;
3af9a47b
NC
1260}
1261
154a1ee5
TG
1262/* Build Mach-O load commands from the sections. */
1263
1264bfd_boolean
1265bfd_mach_o_build_commands (bfd *abfd)
1266{
046b007d 1267 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
c2f09c75 1268 unsigned int wide = mach_o_wide_p (&mdata->header);
154a1ee5
TG
1269 bfd_mach_o_segment_command *seg;
1270 bfd_mach_o_section *sections;
1271 asection *sec;
c2f09c75
TG
1272 bfd_mach_o_load_command *cmd;
1273 bfd_mach_o_load_command *symtab_cmd;
1274 int target_index;
154a1ee5
TG
1275
1276 /* Return now if commands are already built. */
1277 if (mdata->header.ncmds)
1278 return FALSE;
1279
1280 /* Very simple version: 1 command (segment) containing all sections. */
c2f09c75
TG
1281 mdata->header.ncmds = 2;
1282 mdata->commands = bfd_alloc (abfd, mdata->header.ncmds
154a1ee5
TG
1283 * sizeof (bfd_mach_o_load_command));
1284 if (mdata->commands == NULL)
1285 return FALSE;
c2f09c75
TG
1286 cmd = &mdata->commands[0];
1287 seg = &cmd->command.segment;
1288
154a1ee5
TG
1289 seg->nsects = bfd_count_sections (abfd);
1290 sections = bfd_alloc (abfd, seg->nsects * sizeof (bfd_mach_o_section));
1291 if (sections == NULL)
1292 return FALSE;
1293 seg->sections = sections;
1294
1295 /* Set segment command. */
1296 if (wide)
1297 {
c2f09c75
TG
1298 cmd->type = BFD_MACH_O_LC_SEGMENT_64;
1299 cmd->offset = BFD_MACH_O_HEADER_64_SIZE;
1300 cmd->len = BFD_MACH_O_LC_SEGMENT_64_SIZE
154a1ee5
TG
1301 + BFD_MACH_O_SECTION_64_SIZE * seg->nsects;
1302 }
1303 else
1304 {
c2f09c75
TG
1305 cmd->type = BFD_MACH_O_LC_SEGMENT;
1306 cmd->offset = BFD_MACH_O_HEADER_SIZE;
1307 cmd->len = BFD_MACH_O_LC_SEGMENT_SIZE
154a1ee5
TG
1308 + BFD_MACH_O_SECTION_SIZE * seg->nsects;
1309 }
c2f09c75
TG
1310 cmd->type_required = FALSE;
1311 mdata->header.sizeofcmds = cmd->len;
92bc0e80 1312 mdata->filelen = cmd->offset + cmd->len;
154a1ee5 1313
c2f09c75
TG
1314 /* Set symtab command. */
1315 symtab_cmd = &mdata->commands[1];
1316
1317 symtab_cmd->type = BFD_MACH_O_LC_SYMTAB;
1318 symtab_cmd->offset = cmd->offset + cmd->len;
1319 symtab_cmd->len = 6 * 4;
1320 symtab_cmd->type_required = FALSE;
1321
1322 mdata->header.sizeofcmds += symtab_cmd->len;
92bc0e80 1323 mdata->filelen += symtab_cmd->len;
c2f09c75
TG
1324
1325 /* Fill segment command. */
154a1ee5
TG
1326 memset (seg->segname, 0, sizeof (seg->segname));
1327 seg->vmaddr = 0;
92bc0e80 1328 seg->fileoff = mdata->filelen;
154a1ee5
TG
1329 seg->filesize = 0;
1330 seg->maxprot = BFD_MACH_O_PROT_READ | BFD_MACH_O_PROT_WRITE
1331 | BFD_MACH_O_PROT_EXECUTE;
1332 seg->initprot = seg->maxprot;
1333 seg->flags = 0;
1334
1335 /* Create Mach-O sections. */
c2f09c75 1336 target_index = 0;
154a1ee5
TG
1337 for (sec = abfd->sections; sec; sec = sec->next)
1338 {
1339 sections->bfdsection = sec;
1340 bfd_mach_o_convert_section_name_to_mach_o (abfd, sec, sections);
1341 sections->addr = bfd_get_section_vma (abfd, sec);
1342 sections->size = bfd_get_section_size (sec);
1343 sections->align = bfd_get_section_alignment (abfd, sec);
c2f09c75 1344
92bc0e80
TG
1345 if (sections->size != 0)
1346 {
1347 mdata->filelen = FILE_ALIGN (mdata->filelen, sections->align);
1348 sections->offset = mdata->filelen;
1349 }
1350 else
1351 sections->offset = 0;
154a1ee5
TG
1352 sections->reloff = 0;
1353 sections->nreloc = 0;
1354 sections->reserved1 = 0;
1355 sections->reserved2 = 0;
1356 sections->reserved3 = 0;
1357
92bc0e80 1358 sec->filepos = sections->offset;
c2f09c75 1359 sec->target_index = ++target_index;
154a1ee5 1360
92bc0e80 1361 mdata->filelen += sections->size;
154a1ee5
TG
1362 sections++;
1363 }
92bc0e80 1364 seg->filesize = mdata->filelen - seg->fileoff;
154a1ee5
TG
1365 seg->vmsize = seg->filesize;
1366
1367 return TRUE;
1368}
1369
1370/* Set the contents of a section. */
1371
1372bfd_boolean
1373bfd_mach_o_set_section_contents (bfd *abfd,
1374 asection *section,
1375 const void * location,
1376 file_ptr offset,
1377 bfd_size_type count)
1378{
1379 file_ptr pos;
1380
1381 /* This must be done first, because bfd_set_section_contents is
1382 going to set output_has_begun to TRUE. */
1383 if (! abfd->output_has_begun && ! bfd_mach_o_build_commands (abfd))
1384 return FALSE;
1385
1386 if (count == 0)
1387 return TRUE;
1388
1389 pos = section->filepos + offset;
1390 if (bfd_seek (abfd, pos, SEEK_SET) != 0
1391 || bfd_bwrite (location, count, abfd) != count)
1392 return FALSE;
1393
1394 return TRUE;
1395}
1396
1397int
116c20d2 1398bfd_mach_o_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
a6b96beb 1399 struct bfd_link_info *info ATTRIBUTE_UNUSED)
3af9a47b
NC
1400{
1401 return 0;
1402}
1403
1404/* Make an empty symbol. This is required only because
1405 bfd_make_section_anyway wants to create a symbol for the section. */
1406
154a1ee5 1407asymbol *
116c20d2 1408bfd_mach_o_make_empty_symbol (bfd *abfd)
3af9a47b 1409{
d3ce72d0
NC
1410 asymbol *new_symbol;
1411
1412 new_symbol = bfd_zalloc (abfd, sizeof (bfd_mach_o_asymbol));
1413 if (new_symbol == NULL)
1414 return new_symbol;
1415 new_symbol->the_bfd = abfd;
1416 new_symbol->udata.i = 0;
1417 return new_symbol;
3af9a47b
NC
1418}
1419
154a1ee5 1420static bfd_boolean
116c20d2 1421bfd_mach_o_read_header (bfd *abfd, bfd_mach_o_header *header)
3af9a47b 1422{
1e8a024a
TG
1423 unsigned char buf[32];
1424 unsigned int size;
edeb6e24 1425 bfd_vma (*get32) (const void *) = NULL;
3af9a47b 1426
1e8a024a 1427 /* Just read the magic number. */
c2f09c75 1428 if (bfd_seek (abfd, 0, SEEK_SET) != 0
91d6fa6a 1429 || bfd_bread ((void *) buf, 4, abfd) != 4)
154a1ee5 1430 return FALSE;
3af9a47b 1431
154a1ee5 1432 if (bfd_getb32 (buf) == BFD_MACH_O_MH_MAGIC)
3af9a47b
NC
1433 {
1434 header->byteorder = BFD_ENDIAN_BIG;
154a1ee5 1435 header->magic = BFD_MACH_O_MH_MAGIC;
1e8a024a 1436 header->version = 1;
3af9a47b
NC
1437 get32 = bfd_getb32;
1438 }
154a1ee5 1439 else if (bfd_getl32 (buf) == BFD_MACH_O_MH_MAGIC)
3af9a47b 1440 {
a95a4550 1441 header->byteorder = BFD_ENDIAN_LITTLE;
154a1ee5 1442 header->magic = BFD_MACH_O_MH_MAGIC;
1e8a024a
TG
1443 header->version = 1;
1444 get32 = bfd_getl32;
1445 }
154a1ee5 1446 else if (bfd_getb32 (buf) == BFD_MACH_O_MH_MAGIC_64)
1e8a024a
TG
1447 {
1448 header->byteorder = BFD_ENDIAN_BIG;
154a1ee5 1449 header->magic = BFD_MACH_O_MH_MAGIC_64;
1e8a024a
TG
1450 header->version = 2;
1451 get32 = bfd_getb32;
1452 }
154a1ee5 1453 else if (bfd_getl32 (buf) == BFD_MACH_O_MH_MAGIC_64)
1e8a024a
TG
1454 {
1455 header->byteorder = BFD_ENDIAN_LITTLE;
154a1ee5 1456 header->magic = BFD_MACH_O_MH_MAGIC_64;
1e8a024a 1457 header->version = 2;
3af9a47b
NC
1458 get32 = bfd_getl32;
1459 }
1460 else
1461 {
1462 header->byteorder = BFD_ENDIAN_UNKNOWN;
154a1ee5 1463 return FALSE;
3af9a47b 1464 }
a95a4550 1465
1e8a024a 1466 /* Once the size of the header is known, read the full header. */
c2f09c75 1467 size = mach_o_wide_p (header) ?
154a1ee5 1468 BFD_MACH_O_HEADER_64_SIZE : BFD_MACH_O_HEADER_SIZE;
1e8a024a 1469
c2f09c75 1470 if (bfd_seek (abfd, 0, SEEK_SET) != 0
91d6fa6a 1471 || bfd_bread ((void *) buf, size, abfd) != size)
154a1ee5 1472 return FALSE;
1e8a024a 1473
3af9a47b
NC
1474 header->cputype = (*get32) (buf + 4);
1475 header->cpusubtype = (*get32) (buf + 8);
1476 header->filetype = (*get32) (buf + 12);
1477 header->ncmds = (*get32) (buf + 16);
1478 header->sizeofcmds = (*get32) (buf + 20);
1479 header->flags = (*get32) (buf + 24);
1480
c2f09c75 1481 if (mach_o_wide_p (header))
1e8a024a
TG
1482 header->reserved = (*get32) (buf + 28);
1483
154a1ee5 1484 return TRUE;
3af9a47b
NC
1485}
1486
1487static asection *
15e1c58a
TG
1488bfd_mach_o_make_bfd_section (bfd *abfd, bfd_mach_o_section *section,
1489 unsigned long prot)
3af9a47b
NC
1490{
1491 asection *bfdsec;
1492 char *sname;
117ed4f8 1493 flagword flags;
3af9a47b 1494
8462aec7 1495 bfd_mach_o_convert_section_name_to_bfd (abfd, section, &sname, &flags);
3af9a47b
NC
1496 if (sname == NULL)
1497 return NULL;
3af9a47b 1498
8462aec7 1499 if (flags == SEC_NO_FLAGS)
ef17cb22 1500 {
8462aec7
TG
1501 /* Try to guess flags. */
1502 if (section->flags & BFD_MACH_O_S_ATTR_DEBUG)
1503 flags = SEC_DEBUGGING;
1504 else
1505 {
1506 flags = SEC_ALLOC;
1507 if ((section->flags & BFD_MACH_O_SECTION_TYPE_MASK)
1508 != BFD_MACH_O_S_ZEROFILL)
1509 {
1510 flags |= SEC_LOAD;
1511 if (prot & BFD_MACH_O_PROT_EXECUTE)
1512 flags |= SEC_CODE;
1513 if (prot & BFD_MACH_O_PROT_WRITE)
1514 flags |= SEC_DATA;
1515 else if (prot & BFD_MACH_O_PROT_READ)
1516 flags |= SEC_READONLY;
1517 }
1518 }
ef17cb22 1519 }
15e1c58a
TG
1520 else
1521 {
8462aec7
TG
1522 if ((flags & SEC_DEBUGGING) == 0)
1523 flags |= SEC_ALLOC;
15e1c58a 1524 }
8462aec7
TG
1525
1526 if (section->offset != 0)
1527 flags |= SEC_HAS_CONTENTS;
92bc0e80
TG
1528 if (section->nreloc != 0)
1529 flags |= SEC_RELOC;
1530
117ed4f8 1531 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, flags);
3af9a47b
NC
1532 if (bfdsec == NULL)
1533 return NULL;
a95a4550 1534
3af9a47b
NC
1535 bfdsec->vma = section->addr;
1536 bfdsec->lma = section->addr;
eea6121a 1537 bfdsec->size = section->size;
3af9a47b
NC
1538 bfdsec->filepos = section->offset;
1539 bfdsec->alignment_power = section->align;
1e8a024a 1540 bfdsec->segment_mark = 0;
92bc0e80
TG
1541 bfdsec->reloc_count = section->nreloc;
1542 bfdsec->rel_filepos = section->reloff;
3af9a47b 1543
3af9a47b
NC
1544 return bfdsec;
1545}
1546
1547static int
ab273af8
TG
1548bfd_mach_o_read_section_32 (bfd *abfd,
1549 bfd_mach_o_section *section,
1550 unsigned int offset,
1551 unsigned long prot)
3af9a47b 1552{
154a1ee5 1553 unsigned char buf[BFD_MACH_O_SECTION_SIZE];
3af9a47b 1554
c2f09c75 1555 if (bfd_seek (abfd, offset, SEEK_SET) != 0
91d6fa6a 1556 || (bfd_bread ((void *) buf, BFD_MACH_O_SECTION_SIZE, abfd)
c2f09c75 1557 != BFD_MACH_O_SECTION_SIZE))
3af9a47b 1558 return -1;
a95a4550 1559
3af9a47b
NC
1560 memcpy (section->sectname, buf, 16);
1561 section->sectname[16] = '\0';
1562 memcpy (section->segname, buf + 16, 16);
1563 section->segname[16] = '\0';
1564 section->addr = bfd_h_get_32 (abfd, buf + 32);
1565 section->size = bfd_h_get_32 (abfd, buf + 36);
1566 section->offset = bfd_h_get_32 (abfd, buf + 40);
1567 section->align = bfd_h_get_32 (abfd, buf + 44);
1568 section->reloff = bfd_h_get_32 (abfd, buf + 48);
1569 section->nreloc = bfd_h_get_32 (abfd, buf + 52);
1570 section->flags = bfd_h_get_32 (abfd, buf + 56);
1571 section->reserved1 = bfd_h_get_32 (abfd, buf + 60);
1572 section->reserved2 = bfd_h_get_32 (abfd, buf + 64);
1e8a024a 1573 section->reserved3 = 0;
15e1c58a 1574 section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section, prot);
1e8a024a
TG
1575
1576 if (section->bfdsection == NULL)
1577 return -1;
1578
1579 return 0;
1580}
1581
1582static int
ab273af8
TG
1583bfd_mach_o_read_section_64 (bfd *abfd,
1584 bfd_mach_o_section *section,
1585 unsigned int offset,
1586 unsigned long prot)
1e8a024a 1587{
154a1ee5 1588 unsigned char buf[BFD_MACH_O_SECTION_64_SIZE];
1e8a024a 1589
c2f09c75 1590 if (bfd_seek (abfd, offset, SEEK_SET) != 0
91d6fa6a 1591 || (bfd_bread ((void *) buf, BFD_MACH_O_SECTION_64_SIZE, abfd)
c2f09c75 1592 != BFD_MACH_O_SECTION_64_SIZE))
1e8a024a
TG
1593 return -1;
1594
1595 memcpy (section->sectname, buf, 16);
1596 section->sectname[16] = '\0';
1597 memcpy (section->segname, buf + 16, 16);
1598 section->segname[16] = '\0';
1599 section->addr = bfd_h_get_64 (abfd, buf + 32);
1600 section->size = bfd_h_get_64 (abfd, buf + 40);
1601 section->offset = bfd_h_get_32 (abfd, buf + 48);
1602 section->align = bfd_h_get_32 (abfd, buf + 52);
1603 section->reloff = bfd_h_get_32 (abfd, buf + 56);
1604 section->nreloc = bfd_h_get_32 (abfd, buf + 60);
1605 section->flags = bfd_h_get_32 (abfd, buf + 64);
1606 section->reserved1 = bfd_h_get_32 (abfd, buf + 68);
1607 section->reserved2 = bfd_h_get_32 (abfd, buf + 72);
1608 section->reserved3 = bfd_h_get_32 (abfd, buf + 76);
15e1c58a 1609 section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section, prot);
3af9a47b
NC
1610
1611 if (section->bfdsection == NULL)
1612 return -1;
1613
1614 return 0;
1615}
1616
1e8a024a 1617static int
ab273af8
TG
1618bfd_mach_o_read_section (bfd *abfd,
1619 bfd_mach_o_section *section,
1620 unsigned int offset,
1621 unsigned long prot,
1622 unsigned int wide)
1e8a024a
TG
1623{
1624 if (wide)
ab273af8 1625 return bfd_mach_o_read_section_64 (abfd, section, offset, prot);
1e8a024a 1626 else
ab273af8 1627 return bfd_mach_o_read_section_32 (abfd, section, offset, prot);
1e8a024a
TG
1628}
1629
046b007d 1630static int
ab273af8
TG
1631bfd_mach_o_read_symtab_symbol (bfd *abfd,
1632 bfd_mach_o_symtab_command *sym,
1633 bfd_mach_o_asymbol *s,
1634 unsigned long i)
3af9a47b 1635{
046b007d 1636 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
c2f09c75 1637 unsigned int wide = mach_o_wide_p (&mdata->header);
046b007d
TG
1638 unsigned int symwidth =
1639 wide ? BFD_MACH_O_NLIST_64_SIZE : BFD_MACH_O_NLIST_SIZE;
92bc0e80 1640 unsigned int symoff = sym->symoff + (i * symwidth);
1e8a024a 1641 unsigned char buf[16];
3af9a47b
NC
1642 unsigned char type = -1;
1643 unsigned char section = -1;
1644 short desc = -1;
1e8a024a 1645 symvalue value = -1;
3af9a47b
NC
1646 unsigned long stroff = -1;
1647 unsigned int symtype = -1;
1648
1649 BFD_ASSERT (sym->strtab != NULL);
1650
c2f09c75 1651 if (bfd_seek (abfd, symoff, SEEK_SET) != 0
91d6fa6a 1652 || bfd_bread ((void *) buf, symwidth, abfd) != symwidth)
3af9a47b 1653 {
4a97a0e5
AM
1654 (*_bfd_error_handler) (_("bfd_mach_o_read_symtab_symbol: unable to read %d bytes at %lu"),
1655 symwidth, (unsigned long) symoff);
3af9a47b
NC
1656 return -1;
1657 }
1658
1659 stroff = bfd_h_get_32 (abfd, buf);
1660 type = bfd_h_get_8 (abfd, buf + 4);
c2f09c75 1661 symtype = type & BFD_MACH_O_N_TYPE;
15e1c58a 1662 section = bfd_h_get_8 (abfd, buf + 5);
3af9a47b 1663 desc = bfd_h_get_16 (abfd, buf + 6);
1e8a024a
TG
1664 if (wide)
1665 value = bfd_h_get_64 (abfd, buf + 8);
1666 else
1667 value = bfd_h_get_32 (abfd, buf + 8);
3af9a47b
NC
1668
1669 if (stroff >= sym->strsize)
1670 {
4a97a0e5
AM
1671 (*_bfd_error_handler) (_("bfd_mach_o_read_symtab_symbol: symbol name out of range (%lu >= %lu)"),
1672 (unsigned long) stroff,
1673 (unsigned long) sym->strsize);
a95a4550 1674 return -1;
3af9a47b
NC
1675 }
1676
92bc0e80
TG
1677 s->symbol.the_bfd = abfd;
1678 s->symbol.name = sym->strtab + stroff;
1679 s->symbol.value = value;
1680 s->symbol.flags = 0x0;
1681 s->symbol.udata.i = 0;
1682 s->n_type = type;
1683 s->n_sect = section;
1684 s->n_desc = desc;
3af9a47b
NC
1685
1686 if (type & BFD_MACH_O_N_STAB)
1687 {
92bc0e80
TG
1688 s->symbol.flags |= BSF_DEBUGGING;
1689 s->symbol.section = bfd_und_section_ptr;
15e1c58a
TG
1690 switch (type)
1691 {
1692 case N_FUN:
1693 case N_STSYM:
1694 case N_LCSYM:
1695 case N_BNSYM:
1696 case N_SLINE:
1697 case N_ENSYM:
1698 case N_ECOMM:
1699 case N_ECOML:
1700 case N_GSYM:
1701 if ((section > 0) && (section <= mdata->nsects))
1702 {
92bc0e80
TG
1703 s->symbol.section = mdata->sections[section - 1]->bfdsection;
1704 s->symbol.value =
1705 s->symbol.value - mdata->sections[section - 1]->addr;
15e1c58a
TG
1706 }
1707 break;
1708 }
3af9a47b
NC
1709 }
1710 else
1711 {
1712 if (type & BFD_MACH_O_N_PEXT)
92bc0e80 1713 s->symbol.flags |= BSF_GLOBAL;
c2f09c75 1714
3af9a47b 1715 if (type & BFD_MACH_O_N_EXT)
92bc0e80 1716 s->symbol.flags |= BSF_GLOBAL;
15e1c58a
TG
1717
1718 if (!(type & (BFD_MACH_O_N_PEXT | BFD_MACH_O_N_EXT)))
92bc0e80 1719 s->symbol.flags |= BSF_LOCAL;
3af9a47b
NC
1720
1721 switch (symtype)
1722 {
1723 case BFD_MACH_O_N_UNDF:
c2f09c75 1724 if (type == (BFD_MACH_O_N_UNDF | BFD_MACH_O_N_EXT)
92bc0e80 1725 && s->symbol.value != 0)
c2f09c75
TG
1726 {
1727 /* A common symbol. */
92bc0e80
TG
1728 s->symbol.section = bfd_com_section_ptr;
1729 s->symbol.flags = BSF_NO_FLAGS;
c2f09c75
TG
1730 }
1731 else
92bc0e80
TG
1732 {
1733 s->symbol.section = bfd_und_section_ptr;
1734 if (s->n_desc & BFD_MACH_O_N_WEAK_REF)
1735 s->symbol.flags |= BSF_WEAK;
1736 }
3af9a47b
NC
1737 break;
1738 case BFD_MACH_O_N_PBUD:
92bc0e80 1739 s->symbol.section = bfd_und_section_ptr;
3af9a47b
NC
1740 break;
1741 case BFD_MACH_O_N_ABS:
92bc0e80 1742 s->symbol.section = bfd_abs_section_ptr;
3af9a47b
NC
1743 break;
1744 case BFD_MACH_O_N_SECT:
1745 if ((section > 0) && (section <= mdata->nsects))
1746 {
92bc0e80
TG
1747 s->symbol.section = mdata->sections[section - 1]->bfdsection;
1748 s->symbol.value =
1749 s->symbol.value - mdata->sections[section - 1]->addr;
3af9a47b
NC
1750 }
1751 else
1752 {
1753 /* Mach-O uses 0 to mean "no section"; not an error. */
1754 if (section != 0)
1755 {
4a97a0e5
AM
1756 (*_bfd_error_handler) (_("bfd_mach_o_read_symtab_symbol: "
1757 "symbol \"%s\" specified invalid section %d (max %lu): setting to undefined"),
1758 s->symbol.name, section, mdata->nsects);
3af9a47b 1759 }
92bc0e80 1760 s->symbol.section = bfd_und_section_ptr;
3af9a47b
NC
1761 }
1762 break;
1763 case BFD_MACH_O_N_INDR:
4a97a0e5
AM
1764 (*_bfd_error_handler) (_("bfd_mach_o_read_symtab_symbol: "
1765 "symbol \"%s\" is unsupported 'indirect' reference: setting to undefined"),
1766 s->symbol.name);
92bc0e80 1767 s->symbol.section = bfd_und_section_ptr;
3af9a47b
NC
1768 break;
1769 default:
4a97a0e5
AM
1770 (*_bfd_error_handler) (_("bfd_mach_o_read_symtab_symbol: "
1771 "symbol \"%s\" specified invalid type field 0x%x: setting to undefined"),
1772 s->symbol.name, symtype);
92bc0e80 1773 s->symbol.section = bfd_und_section_ptr;
3af9a47b
NC
1774 break;
1775 }
1776 }
1777
1778 return 0;
1779}
1780
046b007d 1781static int
ab273af8 1782bfd_mach_o_read_symtab_strtab (bfd *abfd)
3af9a47b 1783{
046b007d
TG
1784 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
1785 bfd_mach_o_symtab_command *sym = mdata->symtab;
1786
1787 /* Fail if there is no symtab. */
1788 if (sym == NULL)
1789 return -1;
1790
1791 /* Success if already loaded. */
1792 if (sym->strtab)
1793 return 0;
3af9a47b
NC
1794
1795 if (abfd->flags & BFD_IN_MEMORY)
1796 {
1797 struct bfd_in_memory *b;
1798
1799 b = (struct bfd_in_memory *) abfd->iostream;
1800
1801 if ((sym->stroff + sym->strsize) > b->size)
1802 {
1803 bfd_set_error (bfd_error_file_truncated);
1804 return -1;
1805 }
f075ee0c 1806 sym->strtab = (char *) b->buffer + sym->stroff;
3af9a47b 1807 }
046b007d 1808 else
3af9a47b 1809 {
046b007d
TG
1810 sym->strtab = bfd_alloc (abfd, sym->strsize);
1811 if (sym->strtab == NULL)
1812 return -1;
1813
1814 if (bfd_seek (abfd, sym->stroff, SEEK_SET) != 0
91d6fa6a 1815 || bfd_bread ((void *) sym->strtab, sym->strsize, abfd) != sym->strsize)
046b007d
TG
1816 {
1817 bfd_set_error (bfd_error_file_truncated);
1818 return -1;
1819 }
3af9a47b
NC
1820 }
1821
1822 return 0;
1823}
1824
046b007d 1825static int
ab273af8 1826bfd_mach_o_read_symtab_symbols (bfd *abfd)
3af9a47b 1827{
046b007d
TG
1828 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
1829 bfd_mach_o_symtab_command *sym = mdata->symtab;
3af9a47b
NC
1830 unsigned long i;
1831 int ret;
1832
046b007d
TG
1833 if (sym->symbols)
1834 return 0;
1835
92bc0e80 1836 sym->symbols = bfd_alloc (abfd, sym->nsyms * sizeof (bfd_mach_o_asymbol));
3af9a47b
NC
1837
1838 if (sym->symbols == NULL)
1839 {
4a97a0e5 1840 (*_bfd_error_handler) (_("bfd_mach_o_read_symtab_symbols: unable to allocate memory for symbols"));
a95a4550 1841 return -1;
3af9a47b 1842 }
a95a4550 1843
ab273af8 1844 ret = bfd_mach_o_read_symtab_strtab (abfd);
3af9a47b
NC
1845 if (ret != 0)
1846 return ret;
1847
1848 for (i = 0; i < sym->nsyms; i++)
1849 {
ab273af8 1850 ret = bfd_mach_o_read_symtab_symbol (abfd, sym, &sym->symbols[i], i);
3af9a47b
NC
1851 if (ret != 0)
1852 return ret;
1853 }
a95a4550 1854
3af9a47b
NC
1855 return 0;
1856}
1857
1858int
ab273af8
TG
1859bfd_mach_o_read_dysymtab_symbol (bfd *abfd,
1860 bfd_mach_o_dysymtab_command *dysym,
1861 bfd_mach_o_symtab_command *sym,
1862 bfd_mach_o_asymbol *s,
1863 unsigned long i)
3af9a47b
NC
1864{
1865 unsigned long isymoff = dysym->indirectsymoff + (i * 4);
91d6fa6a 1866 unsigned long sym_index;
3af9a47b
NC
1867 unsigned char buf[4];
1868
1869 BFD_ASSERT (i < dysym->nindirectsyms);
a95a4550 1870
c2f09c75 1871 if (bfd_seek (abfd, isymoff, SEEK_SET) != 0
91d6fa6a 1872 || bfd_bread ((void *) buf, 4, abfd) != 4)
3af9a47b 1873 {
4a97a0e5
AM
1874 (*_bfd_error_handler) (_("bfd_mach_o_read_dysymtab_symbol: unable to read %lu bytes at %lu"),
1875 (unsigned long) 4, isymoff);
3af9a47b
NC
1876 return -1;
1877 }
91d6fa6a 1878 sym_index = bfd_h_get_32 (abfd, buf);
a95a4550 1879
91d6fa6a 1880 return bfd_mach_o_read_symtab_symbol (abfd, sym, s, sym_index);
3af9a47b
NC
1881}
1882
1883static const char *
116c20d2 1884bfd_mach_o_i386_flavour_string (unsigned int flavour)
3af9a47b
NC
1885{
1886 switch ((int) flavour)
1887 {
15e1c58a
TG
1888 case BFD_MACH_O_x86_THREAD_STATE32: return "x86_THREAD_STATE32";
1889 case BFD_MACH_O_x86_FLOAT_STATE32: return "x86_FLOAT_STATE32";
1890 case BFD_MACH_O_x86_EXCEPTION_STATE32: return "x86_EXCEPTION_STATE32";
1891 case BFD_MACH_O_x86_THREAD_STATE64: return "x86_THREAD_STATE64";
1892 case BFD_MACH_O_x86_FLOAT_STATE64: return "x86_FLOAT_STATE64";
1893 case BFD_MACH_O_x86_EXCEPTION_STATE64: return "x86_EXCEPTION_STATE64";
1894 case BFD_MACH_O_x86_THREAD_STATE: return "x86_THREAD_STATE";
1895 case BFD_MACH_O_x86_FLOAT_STATE: return "x86_FLOAT_STATE";
1896 case BFD_MACH_O_x86_EXCEPTION_STATE: return "x86_EXCEPTION_STATE";
1897 case BFD_MACH_O_x86_DEBUG_STATE32: return "x86_DEBUG_STATE32";
1898 case BFD_MACH_O_x86_DEBUG_STATE64: return "x86_DEBUG_STATE64";
1899 case BFD_MACH_O_x86_DEBUG_STATE: return "x86_DEBUG_STATE";
b32e07d7 1900 case BFD_MACH_O_x86_THREAD_STATE_NONE: return "x86_THREAD_STATE_NONE";
3af9a47b
NC
1901 default: return "UNKNOWN";
1902 }
1903}
1904
1905static const char *
116c20d2 1906bfd_mach_o_ppc_flavour_string (unsigned int flavour)
3af9a47b
NC
1907{
1908 switch ((int) flavour)
1909 {
b32e07d7
TG
1910 case BFD_MACH_O_PPC_THREAD_STATE: return "PPC_THREAD_STATE";
1911 case BFD_MACH_O_PPC_FLOAT_STATE: return "PPC_FLOAT_STATE";
1912 case BFD_MACH_O_PPC_EXCEPTION_STATE: return "PPC_EXCEPTION_STATE";
1913 case BFD_MACH_O_PPC_VECTOR_STATE: return "PPC_VECTOR_STATE";
1914 case BFD_MACH_O_PPC_THREAD_STATE64: return "PPC_THREAD_STATE64";
1915 case BFD_MACH_O_PPC_EXCEPTION_STATE64: return "PPC_EXCEPTION_STATE64";
3af9a47b
NC
1916 default: return "UNKNOWN";
1917 }
1918}
1919
1920static int
ab273af8 1921bfd_mach_o_read_dylinker (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1922{
1923 bfd_mach_o_dylinker_command *cmd = &command->command.dylinker;
1924 unsigned char buf[4];
1925 unsigned int nameoff;
3af9a47b
NC
1926
1927 BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLINKER)
1928 || (command->type == BFD_MACH_O_LC_LOAD_DYLINKER));
1929
c2f09c75 1930 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 1931 || bfd_bread ((void *) buf, 4, abfd) != 4)
3af9a47b
NC
1932 return -1;
1933
1934 nameoff = bfd_h_get_32 (abfd, buf + 0);
1935
1936 cmd->name_offset = command->offset + nameoff;
1937 cmd->name_len = command->len - nameoff;
b32e07d7
TG
1938 cmd->name_str = bfd_alloc (abfd, cmd->name_len);
1939 if (cmd->name_str == NULL)
3af9a47b 1940 return -1;
b32e07d7
TG
1941 if (bfd_seek (abfd, cmd->name_offset, SEEK_SET) != 0
1942 || bfd_bread (cmd->name_str, cmd->name_len, abfd) != cmd->name_len)
3af9a47b 1943 return -1;
3af9a47b
NC
1944 return 0;
1945}
1946
1947static int
ab273af8 1948bfd_mach_o_read_dylib (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1949{
1950 bfd_mach_o_dylib_command *cmd = &command->command.dylib;
1951 unsigned char buf[16];
1952 unsigned int nameoff;
3af9a47b 1953
046b007d
TG
1954 switch (command->type)
1955 {
1956 case BFD_MACH_O_LC_LOAD_DYLIB:
046b007d 1957 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
046b007d 1958 case BFD_MACH_O_LC_ID_DYLIB:
046b007d 1959 case BFD_MACH_O_LC_REEXPORT_DYLIB:
046b007d
TG
1960 break;
1961 default:
b32e07d7
TG
1962 BFD_FAIL ();
1963 return -1;
046b007d 1964 }
3af9a47b 1965
c2f09c75 1966 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 1967 || bfd_bread ((void *) buf, 16, abfd) != 16)
3af9a47b
NC
1968 return -1;
1969
1970 nameoff = bfd_h_get_32 (abfd, buf + 0);
1971 cmd->timestamp = bfd_h_get_32 (abfd, buf + 4);
1972 cmd->current_version = bfd_h_get_32 (abfd, buf + 8);
1973 cmd->compatibility_version = bfd_h_get_32 (abfd, buf + 12);
1974
1975 cmd->name_offset = command->offset + nameoff;
1976 cmd->name_len = command->len - nameoff;
b32e07d7
TG
1977 cmd->name_str = bfd_alloc (abfd, cmd->name_len);
1978 if (cmd->name_str == NULL)
3af9a47b 1979 return -1;
b32e07d7
TG
1980 if (bfd_seek (abfd, cmd->name_offset, SEEK_SET) != 0
1981 || bfd_bread (cmd->name_str, cmd->name_len, abfd) != cmd->name_len)
3af9a47b 1982 return -1;
3af9a47b
NC
1983 return 0;
1984}
1985
1986static int
ab273af8
TG
1987bfd_mach_o_read_prebound_dylib (bfd *abfd ATTRIBUTE_UNUSED,
1988 bfd_mach_o_load_command *command ATTRIBUTE_UNUSED)
3af9a47b
NC
1989{
1990 /* bfd_mach_o_prebound_dylib_command *cmd = &command->command.prebound_dylib; */
1991
1992 BFD_ASSERT (command->type == BFD_MACH_O_LC_PREBOUND_DYLIB);
1993 return 0;
1994}
1995
1996static int
ab273af8 1997bfd_mach_o_read_thread (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b 1998{
b32e07d7 1999 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b
NC
2000 bfd_mach_o_thread_command *cmd = &command->command.thread;
2001 unsigned char buf[8];
92bc0e80 2002 unsigned int offset;
3af9a47b
NC
2003 unsigned int nflavours;
2004 unsigned int i;
2005
2006 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
2007 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
2008
b32e07d7 2009 /* Count the number of threads. */
3af9a47b
NC
2010 offset = 8;
2011 nflavours = 0;
2012 while (offset != command->len)
2013 {
2014 if (offset >= command->len)
2015 return -1;
2016
c2f09c75 2017 if (bfd_seek (abfd, command->offset + offset, SEEK_SET) != 0
91d6fa6a 2018 || bfd_bread ((void *) buf, 8, abfd) != 8)
3af9a47b
NC
2019 return -1;
2020
2021 offset += 8 + bfd_h_get_32 (abfd, buf + 4) * 4;
2022 nflavours++;
2023 }
2024
b32e07d7
TG
2025 /* Allocate threads. */
2026 cmd->flavours = bfd_alloc
2027 (abfd, nflavours * sizeof (bfd_mach_o_thread_flavour));
3af9a47b
NC
2028 if (cmd->flavours == NULL)
2029 return -1;
2030 cmd->nflavours = nflavours;
2031
2032 offset = 8;
2033 nflavours = 0;
2034 while (offset != command->len)
2035 {
2036 if (offset >= command->len)
2037 return -1;
2038
2039 if (nflavours >= cmd->nflavours)
2040 return -1;
2041
c2f09c75 2042 if (bfd_seek (abfd, command->offset + offset, SEEK_SET) != 0
91d6fa6a 2043 || bfd_bread ((void *) buf, 8, abfd) != 8)
3af9a47b
NC
2044 return -1;
2045
2046 cmd->flavours[nflavours].flavour = bfd_h_get_32 (abfd, buf);
2047 cmd->flavours[nflavours].offset = command->offset + offset + 8;
2048 cmd->flavours[nflavours].size = bfd_h_get_32 (abfd, buf + 4) * 4;
2049 offset += cmd->flavours[nflavours].size + 8;
2050 nflavours++;
2051 }
2052
2053 for (i = 0; i < nflavours; i++)
2054 {
2055 asection *bfdsec;
2056 unsigned int snamelen;
2057 char *sname;
2058 const char *flavourstr;
2059 const char *prefix = "LC_THREAD";
a95a4550
AM
2060 unsigned int j = 0;
2061
3af9a47b
NC
2062 switch (mdata->header.cputype)
2063 {
2064 case BFD_MACH_O_CPU_TYPE_POWERPC:
1e8a024a 2065 case BFD_MACH_O_CPU_TYPE_POWERPC_64:
3af9a47b
NC
2066 flavourstr = bfd_mach_o_ppc_flavour_string (cmd->flavours[i].flavour);
2067 break;
2068 case BFD_MACH_O_CPU_TYPE_I386:
1e8a024a 2069 case BFD_MACH_O_CPU_TYPE_X86_64:
3af9a47b
NC
2070 flavourstr = bfd_mach_o_i386_flavour_string (cmd->flavours[i].flavour);
2071 break;
2072 default:
2073 flavourstr = "UNKNOWN_ARCHITECTURE";
2074 break;
2075 }
a95a4550 2076
3af9a47b 2077 snamelen = strlen (prefix) + 1 + 20 + 1 + strlen (flavourstr) + 1;
116c20d2 2078 sname = bfd_alloc (abfd, snamelen);
3af9a47b
NC
2079 if (sname == NULL)
2080 return -1;
2081
2082 for (;;)
2083 {
a95a4550
AM
2084 sprintf (sname, "%s.%s.%u", prefix, flavourstr, j);
2085 if (bfd_get_section_by_name (abfd, sname) == NULL)
3af9a47b 2086 break;
a95a4550 2087 j++;
3af9a47b
NC
2088 }
2089
117ed4f8 2090 bfdsec = bfd_make_section_with_flags (abfd, sname, SEC_HAS_CONTENTS);
a95a4550 2091
3af9a47b
NC
2092 bfdsec->vma = 0;
2093 bfdsec->lma = 0;
eea6121a 2094 bfdsec->size = cmd->flavours[i].size;
3af9a47b
NC
2095 bfdsec->filepos = cmd->flavours[i].offset;
2096 bfdsec->alignment_power = 0x0;
3af9a47b
NC
2097
2098 cmd->section = bfdsec;
2099 }
2100
2101 return 0;
2102}
2103
a95a4550 2104static int
ab273af8 2105bfd_mach_o_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b 2106{
046b007d 2107 bfd_mach_o_dysymtab_command *cmd = &command->command.dysymtab;
b32e07d7 2108 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b
NC
2109 unsigned char buf[72];
2110
2111 BFD_ASSERT (command->type == BFD_MACH_O_LC_DYSYMTAB);
2112
c2f09c75 2113 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 2114 || bfd_bread ((void *) buf, 72, abfd) != 72)
3af9a47b
NC
2115 return -1;
2116
046b007d
TG
2117 cmd->ilocalsym = bfd_h_get_32 (abfd, buf + 0);
2118 cmd->nlocalsym = bfd_h_get_32 (abfd, buf + 4);
2119 cmd->iextdefsym = bfd_h_get_32 (abfd, buf + 8);
2120 cmd->nextdefsym = bfd_h_get_32 (abfd, buf + 12);
2121 cmd->iundefsym = bfd_h_get_32 (abfd, buf + 16);
2122 cmd->nundefsym = bfd_h_get_32 (abfd, buf + 20);
2123 cmd->tocoff = bfd_h_get_32 (abfd, buf + 24);
2124 cmd->ntoc = bfd_h_get_32 (abfd, buf + 28);
2125 cmd->modtaboff = bfd_h_get_32 (abfd, buf + 32);
2126 cmd->nmodtab = bfd_h_get_32 (abfd, buf + 36);
2127 cmd->extrefsymoff = bfd_h_get_32 (abfd, buf + 40);
2128 cmd->nextrefsyms = bfd_h_get_32 (abfd, buf + 44);
2129 cmd->indirectsymoff = bfd_h_get_32 (abfd, buf + 48);
2130 cmd->nindirectsyms = bfd_h_get_32 (abfd, buf + 52);
2131 cmd->extreloff = bfd_h_get_32 (abfd, buf + 56);
2132 cmd->nextrel = bfd_h_get_32 (abfd, buf + 60);
2133 cmd->locreloff = bfd_h_get_32 (abfd, buf + 64);
2134 cmd->nlocrel = bfd_h_get_32 (abfd, buf + 68);
2135
2136 if (cmd->nmodtab != 0)
2137 {
046b007d
TG
2138 unsigned int i;
2139 int wide = bfd_mach_o_wide_p (abfd);
2140 unsigned int module_len = wide ? 56 : 52;
2141
2142 cmd->dylib_module =
2143 bfd_alloc (abfd, cmd->nmodtab * sizeof (bfd_mach_o_dylib_module));
2144 if (cmd->dylib_module == NULL)
2145 return -1;
2146
2147 if (bfd_seek (abfd, cmd->modtaboff, SEEK_SET) != 0)
2148 return -1;
2149
2150 for (i = 0; i < cmd->nmodtab; i++)
2151 {
2152 bfd_mach_o_dylib_module *module = &cmd->dylib_module[i];
2153 unsigned long v;
2154
91d6fa6a 2155 if (bfd_bread ((void *) buf, module_len, abfd) != module_len)
046b007d
TG
2156 return -1;
2157
2158 module->module_name_idx = bfd_h_get_32 (abfd, buf + 0);
2159 module->iextdefsym = bfd_h_get_32 (abfd, buf + 4);
2160 module->nextdefsym = bfd_h_get_32 (abfd, buf + 8);
2161 module->irefsym = bfd_h_get_32 (abfd, buf + 12);
2162 module->nrefsym = bfd_h_get_32 (abfd, buf + 16);
2163 module->ilocalsym = bfd_h_get_32 (abfd, buf + 20);
2164 module->nlocalsym = bfd_h_get_32 (abfd, buf + 24);
2165 module->iextrel = bfd_h_get_32 (abfd, buf + 28);
2166 module->nextrel = bfd_h_get_32 (abfd, buf + 32);
2167 v = bfd_h_get_32 (abfd, buf +36);
2168 module->iinit = v & 0xffff;
2169 module->iterm = (v >> 16) & 0xffff;
2170 v = bfd_h_get_32 (abfd, buf + 40);
2171 module->ninit = v & 0xffff;
2172 module->nterm = (v >> 16) & 0xffff;
2173 if (wide)
2174 {
2175 module->objc_module_info_size = bfd_h_get_32 (abfd, buf + 44);
2176 module->objc_module_info_addr = bfd_h_get_64 (abfd, buf + 48);
2177 }
2178 else
2179 {
2180 module->objc_module_info_addr = bfd_h_get_32 (abfd, buf + 44);
2181 module->objc_module_info_size = bfd_h_get_32 (abfd, buf + 48);
2182 }
2183 }
2184 }
2185
2186 if (cmd->ntoc != 0)
2187 {
046b007d
TG
2188 unsigned int i;
2189
2190 cmd->dylib_toc = bfd_alloc
2191 (abfd, cmd->ntoc * sizeof (bfd_mach_o_dylib_table_of_content));
2192 if (cmd->dylib_toc == NULL)
2193 return -1;
2194
2195 if (bfd_seek (abfd, cmd->tocoff, SEEK_SET) != 0)
2196 return -1;
2197
2198 for (i = 0; i < cmd->ntoc; i++)
2199 {
2200 bfd_mach_o_dylib_table_of_content *toc = &cmd->dylib_toc[i];
2201
91d6fa6a 2202 if (bfd_bread ((void *) buf, 8, abfd) != 8)
046b007d
TG
2203 return -1;
2204
2205 toc->symbol_index = bfd_h_get_32 (abfd, buf + 0);
2206 toc->module_index = bfd_h_get_32 (abfd, buf + 4);
2207 }
2208 }
2209
2210 if (cmd->nindirectsyms != 0)
2211 {
046b007d
TG
2212 unsigned int i;
2213
2214 cmd->indirect_syms = bfd_alloc
2215 (abfd, cmd->nindirectsyms * sizeof (unsigned int));
2216 if (cmd->indirect_syms == NULL)
2217 return -1;
2218
2219 if (bfd_seek (abfd, cmd->indirectsymoff, SEEK_SET) != 0)
2220 return -1;
2221
2222 for (i = 0; i < cmd->nindirectsyms; i++)
2223 {
2224 unsigned int *is = &cmd->indirect_syms[i];
2225
91d6fa6a 2226 if (bfd_bread ((void *) buf, 4, abfd) != 4)
046b007d
TG
2227 return -1;
2228
2229 *is = bfd_h_get_32 (abfd, buf + 0);
2230 }
2231 }
2232
2233 if (cmd->nextrefsyms != 0)
2234 {
046b007d
TG
2235 unsigned long v;
2236 unsigned int i;
2237
2238 cmd->ext_refs = bfd_alloc
2239 (abfd, cmd->nextrefsyms * sizeof (bfd_mach_o_dylib_reference));
2240 if (cmd->ext_refs == NULL)
2241 return -1;
2242
2243 if (bfd_seek (abfd, cmd->extrefsymoff, SEEK_SET) != 0)
2244 return -1;
2245
2246 for (i = 0; i < cmd->nextrefsyms; i++)
2247 {
2248 bfd_mach_o_dylib_reference *ref = &cmd->ext_refs[i];
2249
91d6fa6a 2250 if (bfd_bread ((void *) buf, 4, abfd) != 4)
046b007d
TG
2251 return -1;
2252
b32e07d7
TG
2253 /* Fields isym and flags are written as bit-fields, thus we need
2254 a specific processing for endianness. */
046b007d 2255 v = bfd_h_get_32 (abfd, buf + 0);
b32e07d7
TG
2256 if (bfd_big_endian (abfd))
2257 {
2258 ref->isym = (v >> 8) & 0xffffff;
2259 ref->flags = v & 0xff;
2260 }
2261 else
2262 {
2263 ref->isym = v & 0xffffff;
2264 ref->flags = (v >> 24) & 0xff;
2265 }
046b007d
TG
2266 }
2267 }
3af9a47b 2268
b32e07d7
TG
2269 if (mdata->dysymtab)
2270 return -1;
2271 mdata->dysymtab = cmd;
2272
3af9a47b
NC
2273 return 0;
2274}
2275
a95a4550 2276static int
ab273af8 2277bfd_mach_o_read_symtab (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b 2278{
046b007d
TG
2279 bfd_mach_o_symtab_command *symtab = &command->command.symtab;
2280 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b 2281 unsigned char buf[16];
3af9a47b
NC
2282
2283 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
2284
c2f09c75 2285 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 2286 || bfd_bread ((void *) buf, 16, abfd) != 16)
3af9a47b 2287 return -1;
a95a4550 2288
046b007d
TG
2289 symtab->symoff = bfd_h_get_32 (abfd, buf);
2290 symtab->nsyms = bfd_h_get_32 (abfd, buf + 4);
2291 symtab->stroff = bfd_h_get_32 (abfd, buf + 8);
2292 symtab->strsize = bfd_h_get_32 (abfd, buf + 12);
2293 symtab->symbols = NULL;
2294 symtab->strtab = NULL;
3af9a47b 2295
046b007d 2296 if (symtab->nsyms != 0)
15e1c58a
TG
2297 abfd->flags |= HAS_SYMS;
2298
046b007d
TG
2299 if (mdata->symtab)
2300 return -1;
2301 mdata->symtab = symtab;
3af9a47b
NC
2302 return 0;
2303}
2304
15e1c58a 2305static int
ab273af8 2306bfd_mach_o_read_uuid (bfd *abfd, bfd_mach_o_load_command *command)
15e1c58a
TG
2307{
2308 bfd_mach_o_uuid_command *cmd = &command->command.uuid;
15e1c58a
TG
2309
2310 BFD_ASSERT (command->type == BFD_MACH_O_LC_UUID);
2311
c2f09c75 2312 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 2313 || bfd_bread ((void *) cmd->uuid, 16, abfd) != 16)
15e1c58a
TG
2314 return -1;
2315
15e1c58a
TG
2316 return 0;
2317}
2318
046b007d 2319static int
ab273af8 2320bfd_mach_o_read_linkedit (bfd *abfd, bfd_mach_o_load_command *command)
046b007d
TG
2321{
2322 bfd_mach_o_linkedit_command *cmd = &command->command.linkedit;
2323 char buf[8];
2324
2325 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 2326 || bfd_bread ((void *) buf, 8, abfd) != 8)
046b007d
TG
2327 return -1;
2328
2329 cmd->dataoff = bfd_get_32 (abfd, buf + 0);
2330 cmd->datasize = bfd_get_32 (abfd, buf + 4);
2331 return 0;
2332}
2333
2334static int
ab273af8 2335bfd_mach_o_read_str (bfd *abfd, bfd_mach_o_load_command *command)
046b007d
TG
2336{
2337 bfd_mach_o_str_command *cmd = &command->command.str;
ad86f1fb 2338 char buf[4];
046b007d
TG
2339 unsigned long off;
2340
2341 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 2342 || bfd_bread ((void *) buf, 4, abfd) != 4)
046b007d
TG
2343 return -1;
2344
2345 off = bfd_get_32 (abfd, buf + 0);
2346 cmd->stroff = command->offset + off;
2347 cmd->str_len = command->len - off;
2348 cmd->str = bfd_alloc (abfd, cmd->str_len);
2349 if (cmd->str == NULL)
2350 return -1;
2351 if (bfd_seek (abfd, cmd->stroff, SEEK_SET) != 0
91d6fa6a 2352 || bfd_bread ((void *) cmd->str, cmd->str_len, abfd) != cmd->str_len)
046b007d
TG
2353 return -1;
2354 return 0;
2355}
2356
ad86f1fb 2357static int
ab273af8 2358bfd_mach_o_read_dyld_info (bfd *abfd, bfd_mach_o_load_command *command)
ad86f1fb
TG
2359{
2360 bfd_mach_o_dyld_info_command *cmd = &command->command.dyld_info;
2361 char buf[40];
2362
2363 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 2364 || bfd_bread ((void *) buf, sizeof (buf), abfd) != sizeof (buf))
ad86f1fb
TG
2365 return -1;
2366
2367 cmd->rebase_off = bfd_get_32 (abfd, buf + 0);
2368 cmd->rebase_size = bfd_get_32 (abfd, buf + 4);
2369 cmd->bind_off = bfd_get_32 (abfd, buf + 8);
2370 cmd->bind_size = bfd_get_32 (abfd, buf + 12);
2371 cmd->weak_bind_off = bfd_get_32 (abfd, buf + 16);
2372 cmd->weak_bind_size = bfd_get_32 (abfd, buf + 20);
2373 cmd->lazy_bind_off = bfd_get_32 (abfd, buf + 24);
2374 cmd->lazy_bind_size = bfd_get_32 (abfd, buf + 28);
2375 cmd->export_off = bfd_get_32 (abfd, buf + 32);
2376 cmd->export_size = bfd_get_32 (abfd, buf + 36);
2377 return 0;
2378}
2379
3af9a47b 2380static int
ab273af8
TG
2381bfd_mach_o_read_segment (bfd *abfd,
2382 bfd_mach_o_load_command *command,
2383 unsigned int wide)
3af9a47b 2384{
1e8a024a 2385 unsigned char buf[64];
3af9a47b
NC
2386 bfd_mach_o_segment_command *seg = &command->command.segment;
2387 unsigned long i;
a95a4550 2388
1e8a024a
TG
2389 if (wide)
2390 {
2391 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT_64);
3af9a47b 2392
c2f09c75 2393 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 2394 || bfd_bread ((void *) buf, 64, abfd) != 64)
1e8a024a 2395 return -1;
3af9a47b 2396
1e8a024a 2397 memcpy (seg->segname, buf, 16);
15e1c58a 2398 seg->segname[16] = '\0';
1e8a024a
TG
2399
2400 seg->vmaddr = bfd_h_get_64 (abfd, buf + 16);
2401 seg->vmsize = bfd_h_get_64 (abfd, buf + 24);
2402 seg->fileoff = bfd_h_get_64 (abfd, buf + 32);
2403 seg->filesize = bfd_h_get_64 (abfd, buf + 40);
2404 seg->maxprot = bfd_h_get_32 (abfd, buf + 48);
2405 seg->initprot = bfd_h_get_32 (abfd, buf + 52);
2406 seg->nsects = bfd_h_get_32 (abfd, buf + 56);
2407 seg->flags = bfd_h_get_32 (abfd, buf + 60);
2408 }
2409 else
2410 {
2411 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
2412
c2f09c75 2413 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
91d6fa6a 2414 || bfd_bread ((void *) buf, 48, abfd) != 48)
1e8a024a
TG
2415 return -1;
2416
2417 memcpy (seg->segname, buf, 16);
15e1c58a 2418 seg->segname[16] = '\0';
1e8a024a
TG
2419
2420 seg->vmaddr = bfd_h_get_32 (abfd, buf + 16);
2421 seg->vmsize = bfd_h_get_32 (abfd, buf + 20);
2422 seg->fileoff = bfd_h_get_32 (abfd, buf + 24);
2423 seg->filesize = bfd_h_get_32 (abfd, buf + 28);
2424 seg->maxprot = bfd_h_get_32 (abfd, buf + 32);
2425 seg->initprot = bfd_h_get_32 (abfd, buf + 36);
2426 seg->nsects = bfd_h_get_32 (abfd, buf + 40);
2427 seg->flags = bfd_h_get_32 (abfd, buf + 44);
2428 }
3af9a47b 2429
3af9a47b
NC
2430 if (seg->nsects != 0)
2431 {
154a1ee5
TG
2432 seg->sections = bfd_alloc (abfd, seg->nsects
2433 * sizeof (bfd_mach_o_section));
3af9a47b
NC
2434 if (seg->sections == NULL)
2435 return -1;
a95a4550 2436
3af9a47b
NC
2437 for (i = 0; i < seg->nsects; i++)
2438 {
1e8a024a 2439 bfd_vma segoff;
154a1ee5 2440 if (wide)
c2f09c75 2441 segoff = command->offset + BFD_MACH_O_LC_SEGMENT_64_SIZE
154a1ee5
TG
2442 + (i * BFD_MACH_O_SECTION_64_SIZE);
2443 else
c2f09c75 2444 segoff = command->offset + BFD_MACH_O_LC_SEGMENT_SIZE
154a1ee5 2445 + (i * BFD_MACH_O_SECTION_SIZE);
3af9a47b 2446
ab273af8 2447 if (bfd_mach_o_read_section
15e1c58a 2448 (abfd, &seg->sections[i], segoff, seg->initprot, wide) != 0)
3af9a47b 2449 return -1;
a95a4550 2450 }
3af9a47b
NC
2451 }
2452
2453 return 0;
2454}
2455
1e8a024a 2456static int
ab273af8 2457bfd_mach_o_read_segment_32 (bfd *abfd, bfd_mach_o_load_command *command)
1e8a024a 2458{
ab273af8 2459 return bfd_mach_o_read_segment (abfd, command, 0);
1e8a024a
TG
2460}
2461
2462static int
ab273af8 2463bfd_mach_o_read_segment_64 (bfd *abfd, bfd_mach_o_load_command *command)
1e8a024a 2464{
ab273af8 2465 return bfd_mach_o_read_segment (abfd, command, 1);
1e8a024a
TG
2466}
2467
3af9a47b 2468static int
ab273af8 2469bfd_mach_o_read_command (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
2470{
2471 unsigned char buf[8];
2472
046b007d 2473 /* Read command type and length. */
c2f09c75 2474 if (bfd_seek (abfd, command->offset, SEEK_SET) != 0
91d6fa6a 2475 || bfd_bread ((void *) buf, 8, abfd) != 8)
3af9a47b
NC
2476 return -1;
2477
154a1ee5 2478 command->type = bfd_h_get_32 (abfd, buf) & ~BFD_MACH_O_LC_REQ_DYLD;
e84d6fca 2479 command->type_required = (bfd_h_get_32 (abfd, buf) & BFD_MACH_O_LC_REQ_DYLD
154a1ee5 2480 ? TRUE : FALSE);
3af9a47b
NC
2481 command->len = bfd_h_get_32 (abfd, buf + 4);
2482
2483 switch (command->type)
2484 {
2485 case BFD_MACH_O_LC_SEGMENT:
ab273af8 2486 if (bfd_mach_o_read_segment_32 (abfd, command) != 0)
1e8a024a
TG
2487 return -1;
2488 break;
2489 case BFD_MACH_O_LC_SEGMENT_64:
ab273af8 2490 if (bfd_mach_o_read_segment_64 (abfd, command) != 0)
3af9a47b
NC
2491 return -1;
2492 break;
2493 case BFD_MACH_O_LC_SYMTAB:
ab273af8 2494 if (bfd_mach_o_read_symtab (abfd, command) != 0)
3af9a47b
NC
2495 return -1;
2496 break;
2497 case BFD_MACH_O_LC_SYMSEG:
2498 break;
2499 case BFD_MACH_O_LC_THREAD:
2500 case BFD_MACH_O_LC_UNIXTHREAD:
ab273af8 2501 if (bfd_mach_o_read_thread (abfd, command) != 0)
3af9a47b
NC
2502 return -1;
2503 break;
2504 case BFD_MACH_O_LC_LOAD_DYLINKER:
2505 case BFD_MACH_O_LC_ID_DYLINKER:
ab273af8 2506 if (bfd_mach_o_read_dylinker (abfd, command) != 0)
3af9a47b
NC
2507 return -1;
2508 break;
2509 case BFD_MACH_O_LC_LOAD_DYLIB:
2510 case BFD_MACH_O_LC_ID_DYLIB:
2511 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
046b007d 2512 case BFD_MACH_O_LC_REEXPORT_DYLIB:
ab273af8 2513 if (bfd_mach_o_read_dylib (abfd, command) != 0)
3af9a47b
NC
2514 return -1;
2515 break;
2516 case BFD_MACH_O_LC_PREBOUND_DYLIB:
ab273af8 2517 if (bfd_mach_o_read_prebound_dylib (abfd, command) != 0)
3af9a47b
NC
2518 return -1;
2519 break;
2520 case BFD_MACH_O_LC_LOADFVMLIB:
2521 case BFD_MACH_O_LC_IDFVMLIB:
2522 case BFD_MACH_O_LC_IDENT:
2523 case BFD_MACH_O_LC_FVMFILE:
2524 case BFD_MACH_O_LC_PREPAGE:
2525 case BFD_MACH_O_LC_ROUTINES:
9b02d212 2526 case BFD_MACH_O_LC_ROUTINES_64:
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 2556 default:
4a97a0e5
AM
2557 (*_bfd_error_handler) (_("unable to read unknown load command 0x%lx"),
2558 (unsigned long) command->type);
3af9a47b
NC
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 {
4a97a0e5
AM
2737 (*_bfd_error_handler) (_("bfd_mach_o_scan: unknown architecture 0x%lx/0x%lx"),
2738 header->cputype, header->cpusubtype);
3af9a47b
NC
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 {
4a97a0e5
AM
2833 (*_bfd_error_handler) (_("unknown header byte-order value 0x%lx"),
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.675931 seconds and 4 git commands to generate.