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