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