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