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