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