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