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