2009-06-12 Tristan Gingold <gingold@adacore.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
c2f09c75 37unsigned int
1e8a024a
TG
38bfd_mach_o_version (bfd *abfd)
39{
40 bfd_mach_o_data_struct *mdata = NULL;
41
42 BFD_ASSERT (bfd_mach_o_valid (abfd));
43 mdata = abfd->tdata.mach_o_data;
44
45 return mdata->header.version;
46}
47
b34976b6 48bfd_boolean
116c20d2 49bfd_mach_o_valid (bfd *abfd)
3af9a47b
NC
50{
51 if (abfd == NULL || abfd->xvec == NULL)
154a1ee5 52 return FALSE;
3af9a47b 53
154a1ee5
TG
54 if (abfd->xvec->flavour != bfd_target_mach_o_flavour)
55 return FALSE;
3af9a47b
NC
56
57 if (abfd->tdata.mach_o_data == NULL)
154a1ee5
TG
58 return FALSE;
59 return TRUE;
60}
61
c2f09c75
TG
62static INLINE bfd_boolean
63mach_o_wide_p (bfd_mach_o_header *header)
64{
65 switch (header->version)
66 {
67 case 1:
68 return FALSE;
69 case 2:
70 return TRUE;
71 default:
72 BFD_FAIL ();
73 return FALSE;
74 }
75}
76
77static INLINE bfd_boolean
78bfd_mach_o_wide_p (bfd *abfd)
79{
80 return mach_o_wide_p (&abfd->tdata.mach_o_data->header);
81}
82
154a1ee5
TG
83/* Tables to translate well known Mach-O segment/section names to bfd
84 names. Use of canonical names (such as .text or .debug_frame) is required
85 by gdb. */
86
87struct mach_o_section_name_xlat
88{
89 const char *bfd_name;
90 const char *mach_o_name;
91};
92
93static const struct mach_o_section_name_xlat dwarf_section_names_xlat[] =
94 {
95 { ".debug_frame", "__debug_frame" },
96 { ".debug_info", "__debug_info" },
97 { ".debug_abbrev", "__debug_abbrev" },
98 { ".debug_aranges", "__debug_aranges" },
99 { ".debug_macinfo", "__debug_macinfo" },
100 { ".debug_line", "__debug_line" },
101 { ".debug_loc", "__debug_loc" },
102 { ".debug_pubnames", "__debug_pubnames" },
103 { ".debug_pubtypes", "__debug_pubtypes" },
104 { ".debug_str", "__debug_str" },
105 { ".debug_ranges", "__debug_ranges" },
106 { NULL, NULL}
107 };
108
109static const struct mach_o_section_name_xlat text_section_names_xlat[] =
110 {
111 { ".text", "__text" },
112 { ".cstring", "__cstring" },
113 { ".eh_frame", "__eh_frame" },
114 { NULL, NULL}
115 };
116
117static const struct mach_o_section_name_xlat data_section_names_xlat[] =
118 {
119 { ".data", "__data" },
120 { ".bss", "__bss" },
121 { NULL, NULL}
122 };
123
124struct mach_o_segment_name_xlat
125{
126 const char *segname;
127 const struct mach_o_section_name_xlat *sections;
128};
129
c2f09c75 130static const struct mach_o_segment_name_xlat segsec_names_xlat[] =
154a1ee5
TG
131 {
132 { "__DWARF", dwarf_section_names_xlat },
133 { "__TEXT", text_section_names_xlat },
134 { "__DATA", data_section_names_xlat },
135 { NULL, NULL }
136 };
137
138
139/* Mach-O to bfd names. */
140
141static char *
142bfd_mach_o_convert_section_name_to_bfd (bfd *abfd, bfd_mach_o_section *section)
143{
144 const struct mach_o_segment_name_xlat *seg;
145 char *res;
146 unsigned int len;
c2f09c75 147 const char *pfx = "";
154a1ee5
TG
148
149 for (seg = segsec_names_xlat; seg->segname; seg++)
150 {
151 if (strcmp (seg->segname, section->segname) == 0)
152 {
153 const struct mach_o_section_name_xlat *sec;
154
155 for (sec = seg->sections; sec->mach_o_name; sec++)
156 {
157 if (strcmp (sec->mach_o_name, section->sectname) == 0)
158 {
159 len = strlen (sec->bfd_name);
160 res = bfd_alloc (abfd, len + 1);
c2f09c75 161
154a1ee5
TG
162 if (res == NULL)
163 return NULL;
164 strcpy (res, sec->bfd_name);
165 return res;
166 }
167 }
168 }
169 }
170
c2f09c75 171 len = strlen (section->segname) + 1
154a1ee5
TG
172 + strlen (section->sectname) + 1;
173
c2f09c75
TG
174 /* Put "LC_SEGMENT." prefix if the segment name is weird (ie doesn't start
175 with an underscore. */
176 if (section->segname[0] != '_')
177 {
178 static const char seg_pfx[] = "LC_SEGMENT.";
179
180 pfx = seg_pfx;
181 len += sizeof (seg_pfx) - 1;
182 }
183
154a1ee5
TG
184 res = bfd_alloc (abfd, len);
185 if (res == NULL)
186 return NULL;
c2f09c75 187 snprintf (res, len, "%s%s.%s", pfx, section->segname, section->sectname);
154a1ee5
TG
188 return res;
189}
190
c2f09c75 191/* Convert a bfd section name to a Mach-O segment + section name. */
154a1ee5
TG
192
193static void
194bfd_mach_o_convert_section_name_to_mach_o (bfd *abfd ATTRIBUTE_UNUSED,
195 asection *sect,
196 bfd_mach_o_section *section)
197{
198 const struct mach_o_segment_name_xlat *seg;
199 const char *name = bfd_get_section_name (abfd, sect);
200 const char *dot;
201 unsigned int len;
202 unsigned int seglen;
203 unsigned int seclen;
204
c2f09c75
TG
205 /* List of well known names. They all start with a dot. */
206 if (name[0] == '.')
207 for (seg = segsec_names_xlat; seg->segname; seg++)
208 {
209 const struct mach_o_section_name_xlat *sec;
210
211 for (sec = seg->sections; sec->mach_o_name; sec++)
212 {
213 if (strcmp (sec->bfd_name, name) == 0)
214 {
215 strcpy (section->segname, seg->segname);
216 strcpy (section->sectname, sec->mach_o_name);
217 return;
218 }
219 }
220 }
154a1ee5
TG
221
222 /* Strip LC_SEGMENT. prefix. */
223 if (strncmp (name, "LC_SEGMENT.", 11) == 0)
224 name += 11;
225
226 /* Find a dot. */
227 dot = strchr (name, '.');
228 len = strlen (name);
229
230 /* Try to split name into segment and section names. */
231 if (dot && dot != name)
232 {
233 seglen = dot - name;
234 seclen = len - (dot + 1 - name);
235
236 if (seglen < 16 && seclen < 16)
237 {
238 memcpy (section->segname, name, seglen);
239 section->segname[seglen] = 0;
240 memcpy (section->sectname, dot + 1, seclen);
241 section->sectname[seclen] = 0;
242 return;
243 }
244 }
245
246 if (len > 16)
247 len = 16;
248 memcpy (section->segname, name, len);
249 section->segname[len] = 0;
250 memcpy (section->sectname, name, len);
251 section->sectname[len] = 0;
3af9a47b
NC
252}
253
254/* Copy any private info we understand from the input symbol
255 to the output symbol. */
256
154a1ee5 257bfd_boolean
116c20d2
NC
258bfd_mach_o_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
259 asymbol *isymbol ATTRIBUTE_UNUSED,
260 bfd *obfd ATTRIBUTE_UNUSED,
261 asymbol *osymbol ATTRIBUTE_UNUSED)
3af9a47b 262{
b34976b6 263 return TRUE;
3af9a47b
NC
264}
265
266/* Copy any private info we understand from the input section
267 to the output section. */
268
154a1ee5 269bfd_boolean
116c20d2
NC
270bfd_mach_o_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
271 asection *isection ATTRIBUTE_UNUSED,
272 bfd *obfd ATTRIBUTE_UNUSED,
273 asection *osection ATTRIBUTE_UNUSED)
3af9a47b 274{
b34976b6 275 return TRUE;
3af9a47b
NC
276}
277
278/* Copy any private info we understand from the input bfd
279 to the output bfd. */
280
154a1ee5 281bfd_boolean
116c20d2 282bfd_mach_o_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
3af9a47b 283{
154a1ee5
TG
284 if (bfd_get_flavour (ibfd) != bfd_target_mach_o_flavour
285 || bfd_get_flavour (obfd) != bfd_target_mach_o_flavour)
286 return TRUE;
287
3af9a47b
NC
288 BFD_ASSERT (bfd_mach_o_valid (ibfd));
289 BFD_ASSERT (bfd_mach_o_valid (obfd));
290
154a1ee5
TG
291 /* FIXME: copy commands. */
292
b34976b6 293 return TRUE;
3af9a47b
NC
294}
295
154a1ee5
TG
296/* Count the total number of symbols. Traverse all sections. */
297
3af9a47b 298static long
116c20d2 299bfd_mach_o_count_symbols (bfd *abfd)
3af9a47b
NC
300{
301 bfd_mach_o_data_struct *mdata = NULL;
302 long nsyms = 0;
303 unsigned long i;
a95a4550 304
3af9a47b
NC
305 BFD_ASSERT (bfd_mach_o_valid (abfd));
306 mdata = abfd->tdata.mach_o_data;
307
308 for (i = 0; i < mdata->header.ncmds; i++)
309 if (mdata->commands[i].type == BFD_MACH_O_LC_SYMTAB)
310 {
311 bfd_mach_o_symtab_command *sym = &mdata->commands[i].command.symtab;
312 nsyms += sym->nsyms;
313 }
314
315 return nsyms;
316}
317
154a1ee5 318long
116c20d2 319bfd_mach_o_get_symtab_upper_bound (bfd *abfd)
3af9a47b
NC
320{
321 long nsyms = bfd_mach_o_count_symbols (abfd);
322
323 if (nsyms < 0)
324 return nsyms;
325
326 return ((nsyms + 1) * sizeof (asymbol *));
327}
328
154a1ee5 329long
116c20d2 330bfd_mach_o_canonicalize_symtab (bfd *abfd, asymbol **alocation)
3af9a47b
NC
331{
332 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
333 long nsyms = bfd_mach_o_count_symbols (abfd);
334 asymbol **csym = alocation;
335 unsigned long i, j;
336
337 if (nsyms < 0)
338 return nsyms;
339
340 for (i = 0; i < mdata->header.ncmds; i++)
341 {
342 if (mdata->commands[i].type == BFD_MACH_O_LC_SYMTAB)
343 {
344 bfd_mach_o_symtab_command *sym = &mdata->commands[i].command.symtab;
345
346 if (bfd_mach_o_scan_read_symtab_symbols (abfd, &mdata->commands[i].command.symtab) != 0)
347 {
6cee3f79 348 fprintf (stderr, "bfd_mach_o_canonicalize_symtab: unable to load symbols for section %lu\n", i);
3af9a47b
NC
349 return 0;
350 }
351
352 BFD_ASSERT (sym->symbols != NULL);
353
354 for (j = 0; j < sym->nsyms; j++)
355 {
356 BFD_ASSERT (csym < (alocation + nsyms));
92bc0e80 357 *csym++ = &sym->symbols[j].symbol;
3af9a47b
NC
358 }
359 }
360 }
361
362 *csym++ = NULL;
a95a4550 363
3af9a47b
NC
364 return nsyms;
365}
366
154a1ee5 367void
116c20d2
NC
368bfd_mach_o_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
369 asymbol *symbol,
370 symbol_info *ret)
3af9a47b
NC
371{
372 bfd_symbol_info (symbol, ret);
373}
374
154a1ee5 375void
116c20d2
NC
376bfd_mach_o_print_symbol (bfd *abfd,
377 PTR afile,
378 asymbol *symbol,
379 bfd_print_symbol_type how)
3af9a47b
NC
380{
381 FILE *file = (FILE *) afile;
15e1c58a 382 const char *name;
92bc0e80 383 bfd_mach_o_asymbol *asym = (bfd_mach_o_asymbol *)symbol;
3af9a47b
NC
384
385 switch (how)
386 {
387 case bfd_print_symbol_name:
388 fprintf (file, "%s", symbol->name);
389 break;
390 default:
391 bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
92bc0e80
TG
392 if (asym->n_type & BFD_MACH_O_N_STAB)
393 name = bfd_get_stab_name (asym->n_type);
15e1c58a 394 else
92bc0e80 395 switch (asym->n_type & BFD_MACH_O_N_TYPE)
15e1c58a
TG
396 {
397 case BFD_MACH_O_N_UNDF:
398 name = "UND";
399 break;
400 case BFD_MACH_O_N_ABS:
401 name = "ABS";
402 break;
403 case BFD_MACH_O_N_INDR:
404 name = "INDR";
405 break;
406 case BFD_MACH_O_N_PBUD:
407 name = "PBUD";
408 break;
409 case BFD_MACH_O_N_SECT:
410 name = "SECT";
411 break;
412 default:
413 name = "???";
414 break;
415 }
416 if (name == NULL)
417 name = "";
92bc0e80
TG
418 fprintf (file, " %02x %-6s %02x %04x",
419 asym->n_type, name, asym->n_sect, asym->n_desc);
420 if ((asym->n_type & BFD_MACH_O_N_STAB) == 0
421 && (asym->n_type & BFD_MACH_O_N_TYPE) == BFD_MACH_O_N_SECT)
15e1c58a
TG
422 fprintf (file, " %-5s", symbol->section->name);
423 fprintf (file, " %s", symbol->name);
3af9a47b
NC
424 }
425}
426
427static void
116c20d2
NC
428bfd_mach_o_convert_architecture (bfd_mach_o_cpu_type mtype,
429 bfd_mach_o_cpu_subtype msubtype ATTRIBUTE_UNUSED,
430 enum bfd_architecture *type,
431 unsigned long *subtype)
3af9a47b
NC
432{
433 *subtype = bfd_arch_unknown;
434
435 switch (mtype)
436 {
437 case BFD_MACH_O_CPU_TYPE_VAX: *type = bfd_arch_vax; break;
438 case BFD_MACH_O_CPU_TYPE_MC680x0: *type = bfd_arch_m68k; break;
1e8a024a
TG
439 case BFD_MACH_O_CPU_TYPE_I386:
440 *type = bfd_arch_i386;
441 *subtype = bfd_mach_i386_i386;
442 break;
443 case BFD_MACH_O_CPU_TYPE_X86_64:
444 *type = bfd_arch_i386;
445 *subtype = bfd_mach_x86_64;
446 break;
3af9a47b
NC
447 case BFD_MACH_O_CPU_TYPE_MIPS: *type = bfd_arch_mips; break;
448 case BFD_MACH_O_CPU_TYPE_MC98000: *type = bfd_arch_m98k; break;
449 case BFD_MACH_O_CPU_TYPE_HPPA: *type = bfd_arch_hppa; break;
450 case BFD_MACH_O_CPU_TYPE_ARM: *type = bfd_arch_arm; break;
451 case BFD_MACH_O_CPU_TYPE_MC88000: *type = bfd_arch_m88k; break;
1e8a024a
TG
452 case BFD_MACH_O_CPU_TYPE_SPARC:
453 *type = bfd_arch_sparc;
454 *subtype = bfd_mach_sparc;
455 break;
3af9a47b
NC
456 case BFD_MACH_O_CPU_TYPE_I860: *type = bfd_arch_i860; break;
457 case BFD_MACH_O_CPU_TYPE_ALPHA: *type = bfd_arch_alpha; break;
1e8a024a
TG
458 case BFD_MACH_O_CPU_TYPE_POWERPC:
459 *type = bfd_arch_powerpc;
c2f09c75 460 *subtype = bfd_mach_ppc;
1e8a024a
TG
461 break;
462 case BFD_MACH_O_CPU_TYPE_POWERPC_64:
463 *type = bfd_arch_powerpc;
c2f09c75 464 *subtype = bfd_mach_ppc64;
1e8a024a 465 break;
3af9a47b 466 default:
1e8a024a
TG
467 *type = bfd_arch_unknown;
468 break;
3af9a47b
NC
469 }
470}
a95a4550 471
154a1ee5 472static bfd_boolean
116c20d2
NC
473bfd_mach_o_write_header (bfd *abfd, bfd_mach_o_header *header)
474{
1e8a024a
TG
475 unsigned char buf[32];
476 unsigned int size;
477
c2f09c75 478 size = mach_o_wide_p (header) ?
154a1ee5 479 BFD_MACH_O_HEADER_64_SIZE : BFD_MACH_O_HEADER_SIZE;
116c20d2
NC
480
481 bfd_h_put_32 (abfd, header->magic, buf + 0);
482 bfd_h_put_32 (abfd, header->cputype, buf + 4);
483 bfd_h_put_32 (abfd, header->cpusubtype, buf + 8);
484 bfd_h_put_32 (abfd, header->filetype, buf + 12);
485 bfd_h_put_32 (abfd, header->ncmds, buf + 16);
486 bfd_h_put_32 (abfd, header->sizeofcmds, buf + 20);
487 bfd_h_put_32 (abfd, header->flags, buf + 24);
488
c2f09c75 489 if (mach_o_wide_p (header))
1e8a024a
TG
490 bfd_h_put_32 (abfd, header->reserved, buf + 28);
491
c2f09c75
TG
492 if (bfd_seek (abfd, 0, SEEK_SET) != 0
493 || bfd_bwrite ((PTR) buf, size, abfd) != size)
154a1ee5 494 return FALSE;
116c20d2 495
154a1ee5 496 return TRUE;
116c20d2
NC
497}
498
499static int
1e8a024a 500bfd_mach_o_scan_write_thread (bfd *abfd, bfd_mach_o_load_command *command)
116c20d2
NC
501{
502 bfd_mach_o_thread_command *cmd = &command->command.thread;
503 unsigned int i;
504 unsigned char buf[8];
92bc0e80 505 unsigned int offset;
116c20d2
NC
506 unsigned int nflavours;
507
508 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
509 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
510
511 offset = 8;
512 nflavours = 0;
513 for (i = 0; i < cmd->nflavours; i++)
514 {
515 BFD_ASSERT ((cmd->flavours[i].size % 4) == 0);
516 BFD_ASSERT (cmd->flavours[i].offset == (command->offset + offset + 8));
517
518 bfd_h_put_32 (abfd, cmd->flavours[i].flavour, buf);
519 bfd_h_put_32 (abfd, (cmd->flavours[i].size / 4), buf + 4);
520
c2f09c75
TG
521 if (bfd_seek (abfd, command->offset + offset, SEEK_SET) != 0
522 || bfd_bwrite ((PTR) buf, 8, abfd) != 8)
116c20d2
NC
523 return -1;
524
525 offset += cmd->flavours[i].size + 8;
526 }
527
528 return 0;
529}
530
92bc0e80
TG
531long
532bfd_mach_o_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
533 asection *asect)
534{
535 return (asect->reloc_count + 1) * sizeof (arelent *);
536}
537
538long
539bfd_mach_o_canonicalize_reloc (bfd *abfd, asection *asect,
540 arelent **rels, asymbol **syms)
541{
542 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
543 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
544 unsigned long i;
545 arelent *res;
546 char *native_relocs;
547 bfd_size_type native_size;
548
549 if (asect->reloc_count == 0)
550 return 0;
551
552 /* No need to go further if we don't know how to read relocs. */
553 if (bed->_bfd_mach_o_swap_reloc_in == NULL)
554 return 0;
555
556 /* Allocate and read relocs. */
557 native_size = asect->reloc_count * BFD_MACH_O_RELENT_SIZE;
558 native_relocs = bfd_malloc (native_size);
559 if (native_relocs == NULL)
560 return -1;
561
562 if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0
563 || bfd_bread (native_relocs, native_size, abfd) != native_size)
564 {
565 free (native_relocs);
566 return -1;
567 }
568
569 res = bfd_malloc (asect->reloc_count * sizeof (arelent));
570 if (res == NULL)
571 {
572 free (native_relocs);
573 return -1;
574 }
575
576 for (i = 0; i < asect->reloc_count; i++)
577 {
578 char *buf = native_relocs + BFD_MACH_O_RELENT_SIZE * i;
579 bfd_mach_o_reloc_info reloc;
580 bfd_vma addr;
581 bfd_vma symnum;
582 asymbol **sym;
583
584 addr = bfd_get_32 (abfd, buf + 0);
585 symnum = bfd_get_32 (abfd, buf + 4);
586
587 if (addr & BFD_MACH_O_SR_SCATTERED)
588 {
589 unsigned int j;
590
591 /* Scattered relocation.
592 Extract section and offset from r_value. */
593 res[i].sym_ptr_ptr = NULL;
594 res[i].addend = 0;
595 for (j = 0; j < mdata->nsects; j++)
596 {
597 bfd_mach_o_section *sect = mdata->sections[j];
598 if (symnum >= sect->addr && symnum < sect->addr + sect->size)
599 {
600 res[i].sym_ptr_ptr = sect->bfdsection->symbol_ptr_ptr;
601 res[i].addend = symnum - sect->addr;
602 break;
603 }
604 }
605 res[i].address = BFD_MACH_O_GET_SR_ADDRESS (addr);
606 reloc.r_type = BFD_MACH_O_GET_SR_TYPE (addr);
607 reloc.r_length = BFD_MACH_O_GET_SR_LENGTH (addr);
608 reloc.r_pcrel = addr & BFD_MACH_O_SR_PCREL;
609 reloc.r_scattered = 1;
610 }
611 else
612 {
613 unsigned int num = BFD_MACH_O_GET_R_SYMBOLNUM (symnum);
614 res[i].addend = 0;
615 res[i].address = addr;
616 if (symnum & BFD_MACH_O_R_EXTERN)
617 sym = syms + num;
618 else
619 {
620 BFD_ASSERT (num != 0);
621 BFD_ASSERT (num <= mdata->nsects);
622 sym = mdata->sections[num - 1]->bfdsection->symbol_ptr_ptr;
623 }
624 res[i].sym_ptr_ptr = sym;
625 reloc.r_type = BFD_MACH_O_GET_R_TYPE (symnum);
626 reloc.r_length = BFD_MACH_O_GET_R_LENGTH (symnum);
627 reloc.r_pcrel = (symnum & BFD_MACH_O_R_PCREL) ? 1 : 0;
628 reloc.r_scattered = 0;
629 }
630
631 if (!(*bed->_bfd_mach_o_swap_reloc_in)(&res[i], &reloc))
632 {
633 free (res);
634 free (native_relocs);
635 return -1;
636 }
637 rels[i] = &res[i];
638 }
639 asect->relocation = res;
640 free (native_relocs);
641 return i;
642}
643
644static bfd_boolean
645bfd_mach_o_scan_write_relocs (bfd *abfd, bfd_mach_o_section *section)
646{
647 bfd_mach_o_data_struct *mdata = bfd_get_mach_o_data (abfd);
648 unsigned int i;
649 arelent **entries;
650 asection *sec;
651 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
652
653 sec = section->bfdsection;
654 if (sec->reloc_count == 0)
655 return TRUE;
656
657 if (bed->_bfd_mach_o_swap_reloc_out == NULL)
658 return TRUE;
659
660 /* Allocate relocation room. */
661 mdata->filelen = FILE_ALIGN(mdata->filelen, 2);
662 section->nreloc = sec->reloc_count;
663 sec->rel_filepos = mdata->filelen;
664 section->reloff = sec->rel_filepos;
665 mdata->filelen += sec->reloc_count * BFD_MACH_O_RELENT_SIZE;
666
667 if (bfd_seek (abfd, section->reloff, SEEK_SET) != 0)
668 return FALSE;
669
670 /* Convert and write. */
671 entries = section->bfdsection->orelocation;
672 for (i = 0; i < section->nreloc; i++)
673 {
674 arelent *rel = entries[i];
675 char buf[8];
676 bfd_mach_o_reloc_info info, *pinfo = &info;
677
678 /* Convert relocation to an intermediate representation. */
679 if (!(*bed->_bfd_mach_o_swap_reloc_out) (rel, pinfo))
680 return FALSE;
681
682 /* Lower the relocation info. */
683 if (pinfo->r_scattered)
684 {
685 unsigned long v;
686
687 v = BFD_MACH_O_SR_SCATTERED
688 | (pinfo->r_pcrel ? BFD_MACH_O_SR_PCREL : 0)
689 | BFD_MACH_O_SET_SR_LENGTH(pinfo->r_length)
690 | BFD_MACH_O_SET_SR_TYPE(pinfo->r_type)
691 | BFD_MACH_O_SET_SR_ADDRESS(pinfo->r_address);
692 bfd_put_32 (abfd, v, buf);
693 bfd_put_32 (abfd, pinfo->r_value, buf + 4);
694 }
695 else
696 {
697 unsigned long v;
698
699 bfd_put_32 (abfd, pinfo->r_address, buf);
700 v = BFD_MACH_O_SET_R_SYMBOLNUM (pinfo->r_value)
701 | (pinfo->r_pcrel ? BFD_MACH_O_R_PCREL : 0)
702 | BFD_MACH_O_SET_R_LENGTH (pinfo->r_length)
703 | (pinfo->r_extern ? BFD_MACH_O_R_EXTERN : 0)
704 | BFD_MACH_O_SET_R_TYPE (pinfo->r_type);
705 bfd_put_32 (abfd, v, buf + 4);
706 }
707
708 if (bfd_bwrite ((PTR) buf, BFD_MACH_O_RELENT_SIZE, abfd)
709 != BFD_MACH_O_RELENT_SIZE)
710 return FALSE;
711 }
712 return TRUE;
713}
714
116c20d2 715static int
92bc0e80 716bfd_mach_o_scan_write_section_32 (bfd *abfd, bfd_mach_o_section *section)
116c20d2 717{
154a1ee5 718 unsigned char buf[BFD_MACH_O_SECTION_SIZE];
116c20d2
NC
719
720 memcpy (buf, section->sectname, 16);
721 memcpy (buf + 16, section->segname, 16);
722 bfd_h_put_32 (abfd, section->addr, buf + 32);
723 bfd_h_put_32 (abfd, section->size, buf + 36);
724 bfd_h_put_32 (abfd, section->offset, buf + 40);
725 bfd_h_put_32 (abfd, section->align, buf + 44);
726 bfd_h_put_32 (abfd, section->reloff, buf + 48);
727 bfd_h_put_32 (abfd, section->nreloc, buf + 52);
728 bfd_h_put_32 (abfd, section->flags, buf + 56);
1e8a024a
TG
729 bfd_h_put_32 (abfd, section->reserved1, buf + 60);
730 bfd_h_put_32 (abfd, section->reserved2, buf + 64);
116c20d2 731
92bc0e80
TG
732 if (bfd_bwrite ((PTR) buf, BFD_MACH_O_SECTION_SIZE, abfd)
733 != BFD_MACH_O_SECTION_SIZE)
116c20d2
NC
734 return -1;
735
736 return 0;
737}
738
739static int
92bc0e80 740bfd_mach_o_scan_write_section_64 (bfd *abfd, bfd_mach_o_section *section)
116c20d2 741{
154a1ee5 742 unsigned char buf[BFD_MACH_O_SECTION_64_SIZE];
116c20d2 743
1e8a024a
TG
744 memcpy (buf, section->sectname, 16);
745 memcpy (buf + 16, section->segname, 16);
746 bfd_h_put_64 (abfd, section->addr, buf + 32);
747 bfd_h_put_64 (abfd, section->size, buf + 40);
748 bfd_h_put_32 (abfd, section->offset, buf + 48);
749 bfd_h_put_32 (abfd, section->align, buf + 52);
750 bfd_h_put_32 (abfd, section->reloff, buf + 56);
751 bfd_h_put_32 (abfd, section->nreloc, buf + 60);
752 bfd_h_put_32 (abfd, section->flags, buf + 64);
753 bfd_h_put_32 (abfd, section->reserved1, buf + 68);
754 bfd_h_put_32 (abfd, section->reserved2, buf + 72);
755 bfd_h_put_32 (abfd, section->reserved3, buf + 76);
116c20d2 756
92bc0e80
TG
757 if (bfd_bwrite ((PTR) buf, BFD_MACH_O_SECTION_64_SIZE, abfd)
758 != BFD_MACH_O_SECTION_64_SIZE)
116c20d2
NC
759 return -1;
760
1e8a024a
TG
761 return 0;
762}
763
764static int
c2f09c75 765bfd_mach_o_scan_write_segment_32 (bfd *abfd, bfd_mach_o_load_command *command)
1e8a024a 766{
c2f09c75 767 unsigned char buf[BFD_MACH_O_LC_SEGMENT_SIZE];
1e8a024a
TG
768 bfd_mach_o_segment_command *seg = &command->command.segment;
769 unsigned long i;
770
c2f09c75
TG
771 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
772
92bc0e80
TG
773 for (i = 0; i < seg->nsects; i++)
774 if (!bfd_mach_o_scan_write_relocs (abfd, &seg->sections[i]))
775 return -1;
c2f09c75 776
92bc0e80 777 memcpy (buf, seg->segname, 16);
c2f09c75
TG
778 bfd_h_put_32 (abfd, seg->vmaddr, buf + 16);
779 bfd_h_put_32 (abfd, seg->vmsize, buf + 20);
780 bfd_h_put_32 (abfd, seg->fileoff, buf + 24);
781 bfd_h_put_32 (abfd, seg->filesize, buf + 28);
782 bfd_h_put_32 (abfd, seg->maxprot, buf + 32);
783 bfd_h_put_32 (abfd, seg->initprot, buf + 36);
784 bfd_h_put_32 (abfd, seg->nsects, buf + 40);
785 bfd_h_put_32 (abfd, seg->flags, buf + 44);
786
787 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
92bc0e80
TG
788 || (bfd_bwrite ((PTR) buf, BFD_MACH_O_LC_SEGMENT_SIZE - 8, abfd)
789 != BFD_MACH_O_LC_SEGMENT_SIZE - 8))
c2f09c75 790 return -1;
1e8a024a 791
116c20d2 792 for (i = 0; i < seg->nsects; i++)
92bc0e80
TG
793 if (bfd_mach_o_scan_write_section_32 (abfd, &seg->sections[i]))
794 return -1;
1e8a024a 795
116c20d2
NC
796 return 0;
797}
798
1e8a024a
TG
799static int
800bfd_mach_o_scan_write_segment_64 (bfd *abfd, bfd_mach_o_load_command *command)
801{
c2f09c75
TG
802 unsigned char buf[BFD_MACH_O_LC_SEGMENT_64_SIZE];
803 bfd_mach_o_segment_command *seg = &command->command.segment;
804 unsigned long i;
805
806 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT_64);
807
92bc0e80
TG
808 for (i = 0; i < seg->nsects; i++)
809 if (!bfd_mach_o_scan_write_relocs (abfd, &seg->sections[i]))
810 return -1;
c2f09c75 811
92bc0e80 812 memcpy (buf, seg->segname, 16);
c2f09c75
TG
813 bfd_h_put_64 (abfd, seg->vmaddr, buf + 16);
814 bfd_h_put_64 (abfd, seg->vmsize, buf + 24);
815 bfd_h_put_64 (abfd, seg->fileoff, buf + 32);
816 bfd_h_put_64 (abfd, seg->filesize, buf + 40);
817 bfd_h_put_32 (abfd, seg->maxprot, buf + 48);
818 bfd_h_put_32 (abfd, seg->initprot, buf + 52);
819 bfd_h_put_32 (abfd, seg->nsects, buf + 56);
820 bfd_h_put_32 (abfd, seg->flags, buf + 60);
821
822 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
92bc0e80
TG
823 || (bfd_bwrite ((PTR) buf, BFD_MACH_O_LC_SEGMENT_64_SIZE - 8, abfd)
824 != BFD_MACH_O_LC_SEGMENT_64_SIZE - 8))
c2f09c75
TG
825 return -1;
826
827 for (i = 0; i < seg->nsects; i++)
92bc0e80
TG
828 if (bfd_mach_o_scan_write_section_64 (abfd, &seg->sections[i]))
829 return -1;
c2f09c75 830
c2f09c75 831 return 0;
1e8a024a
TG
832}
833
c2f09c75
TG
834static bfd_boolean
835bfd_mach_o_scan_write_symtab (bfd *abfd, bfd_mach_o_load_command *command)
116c20d2 836{
92bc0e80 837 bfd_mach_o_data_struct *mdata = bfd_get_mach_o_data (abfd);
116c20d2 838 bfd_mach_o_symtab_command *sym = &command->command.symtab;
c2f09c75 839 unsigned char buf[16];
116c20d2 840 unsigned long i;
c2f09c75
TG
841 unsigned int wide = bfd_mach_o_wide_p (abfd);
842 unsigned int symlen = wide ? 16 : 12;
843 struct bfd_strtab_hash *strtab;
844 asymbol **symbols = bfd_get_outsymbols (abfd);
845
846 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
847
848 /* Write the symbols first. */
92bc0e80
TG
849 mdata->filelen = FILE_ALIGN(mdata->filelen, wide ? 3 : 2);
850 sym->symoff = mdata->filelen;
c2f09c75
TG
851 if (bfd_seek (abfd, sym->symoff, SEEK_SET) != 0)
852 return FALSE;
853
854 sym->nsyms = bfd_get_symcount (abfd);
92bc0e80 855 mdata->filelen += sym->nsyms * symlen;
c2f09c75
TG
856
857 strtab = _bfd_stringtab_init ();
858 if (strtab == NULL)
859 return FALSE;
116c20d2
NC
860
861 for (i = 0; i < sym->nsyms; i++)
862 {
c2f09c75 863 unsigned char buf[16];
c2f09c75 864 bfd_size_type index;
92bc0e80 865 bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i];
c2f09c75 866
92bc0e80 867 /* Compute name index. */
c2f09c75 868 /* An index of 0 always means the empty string. */
92bc0e80 869 if (s->symbol.name == 0 || s->symbol.name[0] == '\0')
c2f09c75
TG
870 index = 0;
871 else
872 {
92bc0e80 873 index = _bfd_stringtab_add (strtab, s->symbol.name, TRUE, FALSE);
c2f09c75
TG
874 if (index == (bfd_size_type) -1)
875 goto err;
876 }
c2f09c75 877 bfd_h_put_32 (abfd, index, buf);
92bc0e80
TG
878 bfd_h_put_8 (abfd, s->n_type, buf + 4);
879 bfd_h_put_8 (abfd, s->n_sect, buf + 5);
880 bfd_h_put_16 (abfd, s->n_desc, buf + 6);
c2f09c75 881 if (wide)
92bc0e80 882 bfd_h_put_64 (abfd, s->symbol.section->vma + s->symbol.value, buf + 8);
c2f09c75 883 else
92bc0e80 884 bfd_h_put_32 (abfd, s->symbol.section->vma + s->symbol.value, buf + 8);
116c20d2 885
c2f09c75
TG
886 if (bfd_bwrite ((PTR) buf, symlen, abfd) != symlen)
887 goto err;
116c20d2 888 }
c2f09c75 889 sym->strsize = _bfd_stringtab_size (strtab);
92bc0e80
TG
890 sym->stroff = mdata->filelen;
891 mdata->filelen += sym->strsize;
116c20d2 892
c2f09c75
TG
893 if (_bfd_stringtab_emit (abfd, strtab) != TRUE)
894 goto err;
895 _bfd_stringtab_free (strtab);
116c20d2 896
c2f09c75
TG
897 /* The command. */
898 bfd_h_put_32 (abfd, sym->symoff, buf);
899 bfd_h_put_32 (abfd, sym->nsyms, buf + 4);
900 bfd_h_put_32 (abfd, sym->stroff, buf + 8);
901 bfd_h_put_32 (abfd, sym->strsize, buf + 12);
116c20d2 902
c2f09c75
TG
903 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
904 || bfd_bwrite ((PTR) buf, 16, abfd) != 16)
905 return FALSE;
116c20d2 906
c2f09c75 907 return TRUE;
116c20d2 908
c2f09c75
TG
909 err:
910 _bfd_stringtab_free (strtab);
911 return FALSE;
116c20d2
NC
912}
913
92bc0e80
TG
914/* Process the symbols and generate Mach-O specific fields.
915 Number them. */
916
917static bfd_boolean
918bfd_mach_o_mangle_symbols (bfd *abfd)
919{
920 unsigned long i;
921 asymbol **symbols = bfd_get_outsymbols (abfd);
922
923 for (i = 0; i < bfd_get_symcount (abfd); i++)
924 {
925 bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i];
926
927 if (s->n_type == BFD_MACH_O_N_UNDF && !(s->symbol.flags & BSF_DEBUGGING))
928 {
929 /* As genuine Mach-O symbols type shouldn't be N_UNDF (undefined
930 symbols should be N_UNDEF | N_EXT), we suppose the back-end
931 values haven't been set. */
932 if (s->symbol.section == bfd_abs_section_ptr)
933 s->n_type = BFD_MACH_O_N_ABS;
934 else if (s->symbol.section == bfd_und_section_ptr)
935 {
936 s->n_type = BFD_MACH_O_N_UNDF;
937 if (s->symbol.flags & BSF_WEAK)
938 s->n_desc |= BFD_MACH_O_N_WEAK_REF;
939 }
940 else if (s->symbol.section == bfd_com_section_ptr)
941 s->n_type = BFD_MACH_O_N_UNDF | BFD_MACH_O_N_EXT;
942 else
943 s->n_type = BFD_MACH_O_N_SECT;
944
945 if (s->symbol.flags & BSF_GLOBAL)
946 s->n_type |= BFD_MACH_O_N_EXT;
947 }
948
949 /* Compute section index. */
950 if (s->symbol.section != bfd_abs_section_ptr
951 && s->symbol.section != bfd_und_section_ptr
952 && s->symbol.section != bfd_com_section_ptr)
953 s->n_sect = s->symbol.section->target_index;
954
955 /* Number symbols. */
956 s->symbol.udata.i = i;
957 }
958 return TRUE;
959}
960
154a1ee5 961bfd_boolean
116c20d2 962bfd_mach_o_write_contents (bfd *abfd)
3af9a47b
NC
963{
964 unsigned int i;
3af9a47b
NC
965 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
966
92bc0e80
TG
967 if (mdata->header.ncmds == 0)
968 if (!bfd_mach_o_build_commands (abfd))
969 return FALSE;
970
3af9a47b 971 /* Now write header information. */
c2f09c75
TG
972 if (mdata->header.filetype == 0)
973 {
974 if (abfd->flags & EXEC_P)
975 mdata->header.filetype = BFD_MACH_O_MH_EXECUTE;
976 else if (abfd->flags & DYNAMIC)
977 mdata->header.filetype = BFD_MACH_O_MH_DYLIB;
978 else
979 mdata->header.filetype = BFD_MACH_O_MH_OBJECT;
980 }
154a1ee5 981 if (!bfd_mach_o_write_header (abfd, &mdata->header))
b34976b6 982 return FALSE;
3af9a47b 983
92bc0e80
TG
984 /* Assign a number to each symbols. */
985 if (!bfd_mach_o_mangle_symbols (abfd))
986 return FALSE;
987
3af9a47b
NC
988 for (i = 0; i < mdata->header.ncmds; i++)
989 {
990 unsigned char buf[8];
991 bfd_mach_o_load_command *cur = &mdata->commands[i];
992 unsigned long typeflag;
993
154a1ee5 994 typeflag = cur->type | (cur->type_required ? BFD_MACH_O_LC_REQ_DYLD : 0);
3af9a47b
NC
995
996 bfd_h_put_32 (abfd, typeflag, buf);
997 bfd_h_put_32 (abfd, cur->len, buf + 4);
998
c2f09c75
TG
999 if (bfd_seek (abfd, cur->offset, SEEK_SET) != 0
1000 || bfd_bwrite ((PTR) buf, 8, abfd) != 8)
b34976b6 1001 return FALSE;
3af9a47b
NC
1002
1003 switch (cur->type)
1004 {
1005 case BFD_MACH_O_LC_SEGMENT:
1e8a024a
TG
1006 if (bfd_mach_o_scan_write_segment_32 (abfd, cur) != 0)
1007 return FALSE;
1008 break;
1009 case BFD_MACH_O_LC_SEGMENT_64:
1010 if (bfd_mach_o_scan_write_segment_64 (abfd, cur) != 0)
b34976b6 1011 return FALSE;
3af9a47b
NC
1012 break;
1013 case BFD_MACH_O_LC_SYMTAB:
c2f09c75 1014 if (!bfd_mach_o_scan_write_symtab (abfd, cur))
b34976b6 1015 return FALSE;
3af9a47b
NC
1016 break;
1017 case BFD_MACH_O_LC_SYMSEG:
1018 break;
1019 case BFD_MACH_O_LC_THREAD:
1020 case BFD_MACH_O_LC_UNIXTHREAD:
1021 if (bfd_mach_o_scan_write_thread (abfd, cur) != 0)
b34976b6 1022 return FALSE;
3af9a47b
NC
1023 break;
1024 case BFD_MACH_O_LC_LOADFVMLIB:
1025 case BFD_MACH_O_LC_IDFVMLIB:
1026 case BFD_MACH_O_LC_IDENT:
1027 case BFD_MACH_O_LC_FVMFILE:
1028 case BFD_MACH_O_LC_PREPAGE:
1029 case BFD_MACH_O_LC_DYSYMTAB:
1030 case BFD_MACH_O_LC_LOAD_DYLIB:
1031 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
1032 case BFD_MACH_O_LC_ID_DYLIB:
1033 case BFD_MACH_O_LC_LOAD_DYLINKER:
1034 case BFD_MACH_O_LC_ID_DYLINKER:
1035 case BFD_MACH_O_LC_PREBOUND_DYLIB:
1036 case BFD_MACH_O_LC_ROUTINES:
1037 case BFD_MACH_O_LC_SUB_FRAMEWORK:
1038 break;
1039 default:
1040 fprintf (stderr,
1041 "unable to write unknown load command 0x%lx\n",
0af1713e 1042 (unsigned long) cur->type);
b34976b6 1043 return FALSE;
3af9a47b
NC
1044 }
1045 }
1046
b34976b6 1047 return TRUE;
3af9a47b
NC
1048}
1049
154a1ee5
TG
1050/* Build Mach-O load commands from the sections. */
1051
1052bfd_boolean
1053bfd_mach_o_build_commands (bfd *abfd)
1054{
1055 bfd_mach_o_data_struct *mdata = bfd_get_mach_o_data (abfd);
c2f09c75 1056 unsigned int wide = mach_o_wide_p (&mdata->header);
154a1ee5
TG
1057 bfd_mach_o_segment_command *seg;
1058 bfd_mach_o_section *sections;
1059 asection *sec;
c2f09c75
TG
1060 bfd_mach_o_load_command *cmd;
1061 bfd_mach_o_load_command *symtab_cmd;
1062 int target_index;
154a1ee5
TG
1063
1064 /* Return now if commands are already built. */
1065 if (mdata->header.ncmds)
1066 return FALSE;
1067
1068 /* Very simple version: 1 command (segment) containing all sections. */
c2f09c75
TG
1069 mdata->header.ncmds = 2;
1070 mdata->commands = bfd_alloc (abfd, mdata->header.ncmds
154a1ee5
TG
1071 * sizeof (bfd_mach_o_load_command));
1072 if (mdata->commands == NULL)
1073 return FALSE;
c2f09c75
TG
1074 cmd = &mdata->commands[0];
1075 seg = &cmd->command.segment;
1076
154a1ee5
TG
1077 seg->nsects = bfd_count_sections (abfd);
1078 sections = bfd_alloc (abfd, seg->nsects * sizeof (bfd_mach_o_section));
1079 if (sections == NULL)
1080 return FALSE;
1081 seg->sections = sections;
1082
1083 /* Set segment command. */
1084 if (wide)
1085 {
c2f09c75
TG
1086 cmd->type = BFD_MACH_O_LC_SEGMENT_64;
1087 cmd->offset = BFD_MACH_O_HEADER_64_SIZE;
1088 cmd->len = BFD_MACH_O_LC_SEGMENT_64_SIZE
154a1ee5
TG
1089 + BFD_MACH_O_SECTION_64_SIZE * seg->nsects;
1090 }
1091 else
1092 {
c2f09c75
TG
1093 cmd->type = BFD_MACH_O_LC_SEGMENT;
1094 cmd->offset = BFD_MACH_O_HEADER_SIZE;
1095 cmd->len = BFD_MACH_O_LC_SEGMENT_SIZE
154a1ee5
TG
1096 + BFD_MACH_O_SECTION_SIZE * seg->nsects;
1097 }
c2f09c75
TG
1098 cmd->type_required = FALSE;
1099 mdata->header.sizeofcmds = cmd->len;
92bc0e80 1100 mdata->filelen = cmd->offset + cmd->len;
154a1ee5 1101
c2f09c75
TG
1102 /* Set symtab command. */
1103 symtab_cmd = &mdata->commands[1];
1104
1105 symtab_cmd->type = BFD_MACH_O_LC_SYMTAB;
1106 symtab_cmd->offset = cmd->offset + cmd->len;
1107 symtab_cmd->len = 6 * 4;
1108 symtab_cmd->type_required = FALSE;
1109
1110 mdata->header.sizeofcmds += symtab_cmd->len;
92bc0e80 1111 mdata->filelen += symtab_cmd->len;
c2f09c75
TG
1112
1113 /* Fill segment command. */
154a1ee5
TG
1114 memset (seg->segname, 0, sizeof (seg->segname));
1115 seg->vmaddr = 0;
92bc0e80 1116 seg->fileoff = mdata->filelen;
154a1ee5
TG
1117 seg->filesize = 0;
1118 seg->maxprot = BFD_MACH_O_PROT_READ | BFD_MACH_O_PROT_WRITE
1119 | BFD_MACH_O_PROT_EXECUTE;
1120 seg->initprot = seg->maxprot;
1121 seg->flags = 0;
1122
1123 /* Create Mach-O sections. */
c2f09c75 1124 target_index = 0;
154a1ee5
TG
1125 for (sec = abfd->sections; sec; sec = sec->next)
1126 {
1127 sections->bfdsection = sec;
1128 bfd_mach_o_convert_section_name_to_mach_o (abfd, sec, sections);
1129 sections->addr = bfd_get_section_vma (abfd, sec);
1130 sections->size = bfd_get_section_size (sec);
1131 sections->align = bfd_get_section_alignment (abfd, sec);
c2f09c75 1132
92bc0e80
TG
1133 if (sections->size != 0)
1134 {
1135 mdata->filelen = FILE_ALIGN (mdata->filelen, sections->align);
1136 sections->offset = mdata->filelen;
1137 }
1138 else
1139 sections->offset = 0;
154a1ee5
TG
1140 sections->reloff = 0;
1141 sections->nreloc = 0;
1142 sections->reserved1 = 0;
1143 sections->reserved2 = 0;
1144 sections->reserved3 = 0;
1145
92bc0e80 1146 sec->filepos = sections->offset;
c2f09c75 1147 sec->target_index = ++target_index;
154a1ee5 1148
92bc0e80 1149 mdata->filelen += sections->size;
154a1ee5
TG
1150 sections++;
1151 }
92bc0e80 1152 seg->filesize = mdata->filelen - seg->fileoff;
154a1ee5
TG
1153 seg->vmsize = seg->filesize;
1154
1155 return TRUE;
1156}
1157
1158/* Set the contents of a section. */
1159
1160bfd_boolean
1161bfd_mach_o_set_section_contents (bfd *abfd,
1162 asection *section,
1163 const void * location,
1164 file_ptr offset,
1165 bfd_size_type count)
1166{
1167 file_ptr pos;
1168
1169 /* This must be done first, because bfd_set_section_contents is
1170 going to set output_has_begun to TRUE. */
1171 if (! abfd->output_has_begun && ! bfd_mach_o_build_commands (abfd))
1172 return FALSE;
1173
1174 if (count == 0)
1175 return TRUE;
1176
1177 pos = section->filepos + offset;
1178 if (bfd_seek (abfd, pos, SEEK_SET) != 0
1179 || bfd_bwrite (location, count, abfd) != count)
1180 return FALSE;
1181
1182 return TRUE;
1183}
1184
1185int
116c20d2 1186bfd_mach_o_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
a6b96beb 1187 struct bfd_link_info *info ATTRIBUTE_UNUSED)
3af9a47b
NC
1188{
1189 return 0;
1190}
1191
1192/* Make an empty symbol. This is required only because
1193 bfd_make_section_anyway wants to create a symbol for the section. */
1194
154a1ee5 1195asymbol *
116c20d2 1196bfd_mach_o_make_empty_symbol (bfd *abfd)
3af9a47b
NC
1197{
1198 asymbol *new;
1199
92bc0e80 1200 new = bfd_zalloc (abfd, sizeof (bfd_mach_o_asymbol));
3af9a47b
NC
1201 if (new == NULL)
1202 return new;
1203 new->the_bfd = abfd;
92bc0e80 1204 new->udata.i = 0;
3af9a47b
NC
1205 return new;
1206}
1207
154a1ee5 1208static bfd_boolean
116c20d2 1209bfd_mach_o_read_header (bfd *abfd, bfd_mach_o_header *header)
3af9a47b 1210{
1e8a024a
TG
1211 unsigned char buf[32];
1212 unsigned int size;
edeb6e24 1213 bfd_vma (*get32) (const void *) = NULL;
3af9a47b 1214
1e8a024a 1215 /* Just read the magic number. */
c2f09c75
TG
1216 if (bfd_seek (abfd, 0, SEEK_SET) != 0
1217 || bfd_bread ((PTR) buf, 4, abfd) != 4)
154a1ee5 1218 return FALSE;
3af9a47b 1219
154a1ee5 1220 if (bfd_getb32 (buf) == BFD_MACH_O_MH_MAGIC)
3af9a47b
NC
1221 {
1222 header->byteorder = BFD_ENDIAN_BIG;
154a1ee5 1223 header->magic = BFD_MACH_O_MH_MAGIC;
1e8a024a 1224 header->version = 1;
3af9a47b
NC
1225 get32 = bfd_getb32;
1226 }
154a1ee5 1227 else if (bfd_getl32 (buf) == BFD_MACH_O_MH_MAGIC)
3af9a47b 1228 {
a95a4550 1229 header->byteorder = BFD_ENDIAN_LITTLE;
154a1ee5 1230 header->magic = BFD_MACH_O_MH_MAGIC;
1e8a024a
TG
1231 header->version = 1;
1232 get32 = bfd_getl32;
1233 }
154a1ee5 1234 else if (bfd_getb32 (buf) == BFD_MACH_O_MH_MAGIC_64)
1e8a024a
TG
1235 {
1236 header->byteorder = BFD_ENDIAN_BIG;
154a1ee5 1237 header->magic = BFD_MACH_O_MH_MAGIC_64;
1e8a024a
TG
1238 header->version = 2;
1239 get32 = bfd_getb32;
1240 }
154a1ee5 1241 else if (bfd_getl32 (buf) == BFD_MACH_O_MH_MAGIC_64)
1e8a024a
TG
1242 {
1243 header->byteorder = BFD_ENDIAN_LITTLE;
154a1ee5 1244 header->magic = BFD_MACH_O_MH_MAGIC_64;
1e8a024a 1245 header->version = 2;
3af9a47b
NC
1246 get32 = bfd_getl32;
1247 }
1248 else
1249 {
1250 header->byteorder = BFD_ENDIAN_UNKNOWN;
154a1ee5 1251 return FALSE;
3af9a47b 1252 }
a95a4550 1253
1e8a024a 1254 /* Once the size of the header is known, read the full header. */
c2f09c75 1255 size = mach_o_wide_p (header) ?
154a1ee5 1256 BFD_MACH_O_HEADER_64_SIZE : BFD_MACH_O_HEADER_SIZE;
1e8a024a 1257
c2f09c75
TG
1258 if (bfd_seek (abfd, 0, SEEK_SET) != 0
1259 || bfd_bread ((PTR) buf, size, abfd) != size)
154a1ee5 1260 return FALSE;
1e8a024a 1261
3af9a47b
NC
1262 header->cputype = (*get32) (buf + 4);
1263 header->cpusubtype = (*get32) (buf + 8);
1264 header->filetype = (*get32) (buf + 12);
1265 header->ncmds = (*get32) (buf + 16);
1266 header->sizeofcmds = (*get32) (buf + 20);
1267 header->flags = (*get32) (buf + 24);
1268
c2f09c75 1269 if (mach_o_wide_p (header))
1e8a024a
TG
1270 header->reserved = (*get32) (buf + 28);
1271
154a1ee5 1272 return TRUE;
3af9a47b
NC
1273}
1274
1275static asection *
15e1c58a
TG
1276bfd_mach_o_make_bfd_section (bfd *abfd, bfd_mach_o_section *section,
1277 unsigned long prot)
3af9a47b
NC
1278{
1279 asection *bfdsec;
1280 char *sname;
117ed4f8 1281 flagword flags;
3af9a47b 1282
154a1ee5 1283 sname = bfd_mach_o_convert_section_name_to_bfd (abfd, section);
3af9a47b
NC
1284 if (sname == NULL)
1285 return NULL;
3af9a47b 1286
15e1c58a
TG
1287 if (section->flags & BFD_MACH_O_S_ATTR_DEBUG)
1288 flags = SEC_HAS_CONTENTS | SEC_DEBUGGING;
1289 else
1290 {
1291 flags = SEC_ALLOC;
1292 if ((section->flags & BFD_MACH_O_SECTION_TYPE_MASK)
1293 != BFD_MACH_O_S_ZEROFILL)
1294 {
1295 flags |= SEC_HAS_CONTENTS | SEC_LOAD;
1296 if (prot & BFD_MACH_O_PROT_EXECUTE)
1297 flags |= SEC_CODE;
1298 if (prot & BFD_MACH_O_PROT_WRITE)
1299 flags |= SEC_DATA;
1300 else if (prot & BFD_MACH_O_PROT_READ)
1301 flags |= SEC_READONLY;
1302 }
1303 }
92bc0e80
TG
1304 if (section->nreloc != 0)
1305 flags |= SEC_RELOC;
1306
117ed4f8 1307 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, flags);
3af9a47b
NC
1308 if (bfdsec == NULL)
1309 return NULL;
a95a4550 1310
3af9a47b
NC
1311 bfdsec->vma = section->addr;
1312 bfdsec->lma = section->addr;
eea6121a 1313 bfdsec->size = section->size;
3af9a47b
NC
1314 bfdsec->filepos = section->offset;
1315 bfdsec->alignment_power = section->align;
1e8a024a 1316 bfdsec->segment_mark = 0;
92bc0e80
TG
1317 bfdsec->reloc_count = section->nreloc;
1318 bfdsec->rel_filepos = section->reloff;
3af9a47b 1319
3af9a47b
NC
1320 return bfdsec;
1321}
1322
1323static int
1e8a024a
TG
1324bfd_mach_o_scan_read_section_32 (bfd *abfd,
1325 bfd_mach_o_section *section,
92bc0e80 1326 unsigned int offset,
15e1c58a 1327 unsigned long prot)
3af9a47b 1328{
154a1ee5 1329 unsigned char buf[BFD_MACH_O_SECTION_SIZE];
3af9a47b 1330
c2f09c75
TG
1331 if (bfd_seek (abfd, offset, SEEK_SET) != 0
1332 || (bfd_bread ((PTR) buf, BFD_MACH_O_SECTION_SIZE, abfd)
1333 != BFD_MACH_O_SECTION_SIZE))
3af9a47b 1334 return -1;
a95a4550 1335
3af9a47b
NC
1336 memcpy (section->sectname, buf, 16);
1337 section->sectname[16] = '\0';
1338 memcpy (section->segname, buf + 16, 16);
1339 section->segname[16] = '\0';
1340 section->addr = bfd_h_get_32 (abfd, buf + 32);
1341 section->size = bfd_h_get_32 (abfd, buf + 36);
1342 section->offset = bfd_h_get_32 (abfd, buf + 40);
1343 section->align = bfd_h_get_32 (abfd, buf + 44);
1344 section->reloff = bfd_h_get_32 (abfd, buf + 48);
1345 section->nreloc = bfd_h_get_32 (abfd, buf + 52);
1346 section->flags = bfd_h_get_32 (abfd, buf + 56);
1347 section->reserved1 = bfd_h_get_32 (abfd, buf + 60);
1348 section->reserved2 = bfd_h_get_32 (abfd, buf + 64);
1e8a024a 1349 section->reserved3 = 0;
15e1c58a 1350 section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section, prot);
1e8a024a
TG
1351
1352 if (section->bfdsection == NULL)
1353 return -1;
1354
1355 return 0;
1356}
1357
1358static int
1359bfd_mach_o_scan_read_section_64 (bfd *abfd,
1360 bfd_mach_o_section *section,
92bc0e80 1361 unsigned int offset,
15e1c58a 1362 unsigned long prot)
1e8a024a 1363{
154a1ee5 1364 unsigned char buf[BFD_MACH_O_SECTION_64_SIZE];
1e8a024a 1365
c2f09c75
TG
1366 if (bfd_seek (abfd, offset, SEEK_SET) != 0
1367 || (bfd_bread ((PTR) buf, BFD_MACH_O_SECTION_64_SIZE, abfd)
1368 != BFD_MACH_O_SECTION_64_SIZE))
1e8a024a
TG
1369 return -1;
1370
1371 memcpy (section->sectname, buf, 16);
1372 section->sectname[16] = '\0';
1373 memcpy (section->segname, buf + 16, 16);
1374 section->segname[16] = '\0';
1375 section->addr = bfd_h_get_64 (abfd, buf + 32);
1376 section->size = bfd_h_get_64 (abfd, buf + 40);
1377 section->offset = bfd_h_get_32 (abfd, buf + 48);
1378 section->align = bfd_h_get_32 (abfd, buf + 52);
1379 section->reloff = bfd_h_get_32 (abfd, buf + 56);
1380 section->nreloc = bfd_h_get_32 (abfd, buf + 60);
1381 section->flags = bfd_h_get_32 (abfd, buf + 64);
1382 section->reserved1 = bfd_h_get_32 (abfd, buf + 68);
1383 section->reserved2 = bfd_h_get_32 (abfd, buf + 72);
1384 section->reserved3 = bfd_h_get_32 (abfd, buf + 76);
15e1c58a 1385 section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section, prot);
3af9a47b
NC
1386
1387 if (section->bfdsection == NULL)
1388 return -1;
1389
1390 return 0;
1391}
1392
1e8a024a
TG
1393static int
1394bfd_mach_o_scan_read_section (bfd *abfd,
1395 bfd_mach_o_section *section,
92bc0e80 1396 unsigned int offset,
15e1c58a 1397 unsigned long prot,
1e8a024a
TG
1398 unsigned int wide)
1399{
1400 if (wide)
15e1c58a 1401 return bfd_mach_o_scan_read_section_64 (abfd, section, offset, prot);
1e8a024a 1402 else
15e1c58a 1403 return bfd_mach_o_scan_read_section_32 (abfd, section, offset, prot);
1e8a024a
TG
1404}
1405
3af9a47b 1406int
116c20d2
NC
1407bfd_mach_o_scan_read_symtab_symbol (bfd *abfd,
1408 bfd_mach_o_symtab_command *sym,
92bc0e80 1409 bfd_mach_o_asymbol *s,
116c20d2 1410 unsigned long i)
3af9a47b
NC
1411{
1412 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
c2f09c75 1413 unsigned int wide = mach_o_wide_p (&mdata->header);
1e8a024a 1414 unsigned int symwidth = wide ? 16 : 12;
92bc0e80 1415 unsigned int symoff = sym->symoff + (i * symwidth);
1e8a024a 1416 unsigned char buf[16];
3af9a47b
NC
1417 unsigned char type = -1;
1418 unsigned char section = -1;
1419 short desc = -1;
1e8a024a 1420 symvalue value = -1;
3af9a47b
NC
1421 unsigned long stroff = -1;
1422 unsigned int symtype = -1;
1423
1424 BFD_ASSERT (sym->strtab != NULL);
1425
c2f09c75
TG
1426 if (bfd_seek (abfd, symoff, SEEK_SET) != 0
1427 || bfd_bread ((PTR) buf, symwidth, abfd) != symwidth)
3af9a47b
NC
1428 {
1429 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: unable to read %d bytes at %lu\n",
1e8a024a 1430 symwidth, (unsigned long) symoff);
3af9a47b
NC
1431 return -1;
1432 }
1433
1434 stroff = bfd_h_get_32 (abfd, buf);
1435 type = bfd_h_get_8 (abfd, buf + 4);
c2f09c75 1436 symtype = type & BFD_MACH_O_N_TYPE;
15e1c58a 1437 section = bfd_h_get_8 (abfd, buf + 5);
3af9a47b 1438 desc = bfd_h_get_16 (abfd, buf + 6);
1e8a024a
TG
1439 if (wide)
1440 value = bfd_h_get_64 (abfd, buf + 8);
1441 else
1442 value = bfd_h_get_32 (abfd, buf + 8);
3af9a47b
NC
1443
1444 if (stroff >= sym->strsize)
1445 {
1446 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: symbol name out of range (%lu >= %lu)\n",
1447 (unsigned long) stroff, (unsigned long) sym->strsize);
a95a4550 1448 return -1;
3af9a47b
NC
1449 }
1450
92bc0e80
TG
1451 s->symbol.the_bfd = abfd;
1452 s->symbol.name = sym->strtab + stroff;
1453 s->symbol.value = value;
1454 s->symbol.flags = 0x0;
1455 s->symbol.udata.i = 0;
1456 s->n_type = type;
1457 s->n_sect = section;
1458 s->n_desc = desc;
3af9a47b
NC
1459
1460 if (type & BFD_MACH_O_N_STAB)
1461 {
92bc0e80
TG
1462 s->symbol.flags |= BSF_DEBUGGING;
1463 s->symbol.section = bfd_und_section_ptr;
15e1c58a
TG
1464 switch (type)
1465 {
1466 case N_FUN:
1467 case N_STSYM:
1468 case N_LCSYM:
1469 case N_BNSYM:
1470 case N_SLINE:
1471 case N_ENSYM:
1472 case N_ECOMM:
1473 case N_ECOML:
1474 case N_GSYM:
1475 if ((section > 0) && (section <= mdata->nsects))
1476 {
92bc0e80
TG
1477 s->symbol.section = mdata->sections[section - 1]->bfdsection;
1478 s->symbol.value =
1479 s->symbol.value - mdata->sections[section - 1]->addr;
15e1c58a
TG
1480 }
1481 break;
1482 }
3af9a47b
NC
1483 }
1484 else
1485 {
1486 if (type & BFD_MACH_O_N_PEXT)
92bc0e80 1487 s->symbol.flags |= BSF_GLOBAL;
c2f09c75 1488
3af9a47b 1489 if (type & BFD_MACH_O_N_EXT)
92bc0e80 1490 s->symbol.flags |= BSF_GLOBAL;
15e1c58a
TG
1491
1492 if (!(type & (BFD_MACH_O_N_PEXT | BFD_MACH_O_N_EXT)))
92bc0e80 1493 s->symbol.flags |= BSF_LOCAL;
3af9a47b
NC
1494
1495 switch (symtype)
1496 {
1497 case BFD_MACH_O_N_UNDF:
c2f09c75 1498 if (type == (BFD_MACH_O_N_UNDF | BFD_MACH_O_N_EXT)
92bc0e80 1499 && s->symbol.value != 0)
c2f09c75
TG
1500 {
1501 /* A common symbol. */
92bc0e80
TG
1502 s->symbol.section = bfd_com_section_ptr;
1503 s->symbol.flags = BSF_NO_FLAGS;
c2f09c75
TG
1504 }
1505 else
92bc0e80
TG
1506 {
1507 s->symbol.section = bfd_und_section_ptr;
1508 if (s->n_desc & BFD_MACH_O_N_WEAK_REF)
1509 s->symbol.flags |= BSF_WEAK;
1510 }
3af9a47b
NC
1511 break;
1512 case BFD_MACH_O_N_PBUD:
92bc0e80 1513 s->symbol.section = bfd_und_section_ptr;
3af9a47b
NC
1514 break;
1515 case BFD_MACH_O_N_ABS:
92bc0e80 1516 s->symbol.section = bfd_abs_section_ptr;
3af9a47b
NC
1517 break;
1518 case BFD_MACH_O_N_SECT:
1519 if ((section > 0) && (section <= mdata->nsects))
1520 {
92bc0e80
TG
1521 s->symbol.section = mdata->sections[section - 1]->bfdsection;
1522 s->symbol.value =
1523 s->symbol.value - mdata->sections[section - 1]->addr;
3af9a47b
NC
1524 }
1525 else
1526 {
1527 /* Mach-O uses 0 to mean "no section"; not an error. */
1528 if (section != 0)
1529 {
1530 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
a95a4550 1531 "symbol \"%s\" specified invalid section %d (max %lu): setting to undefined\n",
92bc0e80 1532 s->symbol.name, section, mdata->nsects);
3af9a47b 1533 }
92bc0e80 1534 s->symbol.section = bfd_und_section_ptr;
3af9a47b
NC
1535 }
1536 break;
1537 case BFD_MACH_O_N_INDR:
1538 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
a95a4550 1539 "symbol \"%s\" is unsupported 'indirect' reference: setting to undefined\n",
92bc0e80
TG
1540 s->symbol.name);
1541 s->symbol.section = bfd_und_section_ptr;
3af9a47b
NC
1542 break;
1543 default:
1544 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
a95a4550 1545 "symbol \"%s\" specified invalid type field 0x%x: setting to undefined\n",
92bc0e80
TG
1546 s->symbol.name, symtype);
1547 s->symbol.section = bfd_und_section_ptr;
3af9a47b
NC
1548 break;
1549 }
1550 }
1551
1552 return 0;
1553}
1554
1555int
116c20d2
NC
1556bfd_mach_o_scan_read_symtab_strtab (bfd *abfd,
1557 bfd_mach_o_symtab_command *sym)
3af9a47b
NC
1558{
1559 BFD_ASSERT (sym->strtab == NULL);
1560
1561 if (abfd->flags & BFD_IN_MEMORY)
1562 {
1563 struct bfd_in_memory *b;
1564
1565 b = (struct bfd_in_memory *) abfd->iostream;
1566
1567 if ((sym->stroff + sym->strsize) > b->size)
1568 {
1569 bfd_set_error (bfd_error_file_truncated);
1570 return -1;
1571 }
f075ee0c 1572 sym->strtab = (char *) b->buffer + sym->stroff;
3af9a47b
NC
1573 return 0;
1574 }
1575
1576 sym->strtab = bfd_alloc (abfd, sym->strsize);
1577 if (sym->strtab == NULL)
1578 return -1;
1579
c2f09c75
TG
1580 if (bfd_seek (abfd, sym->stroff, SEEK_SET) != 0
1581 || bfd_bread ((PTR) sym->strtab, sym->strsize, abfd) != sym->strsize)
3af9a47b 1582 {
92bc0e80 1583 bfd_set_error (bfd_error_file_truncated);
a95a4550 1584 return -1;
3af9a47b
NC
1585 }
1586
1587 return 0;
1588}
1589
a95a4550 1590int
116c20d2
NC
1591bfd_mach_o_scan_read_symtab_symbols (bfd *abfd,
1592 bfd_mach_o_symtab_command *sym)
3af9a47b
NC
1593{
1594 unsigned long i;
1595 int ret;
1596
1597 BFD_ASSERT (sym->symbols == NULL);
92bc0e80 1598 sym->symbols = bfd_alloc (abfd, sym->nsyms * sizeof (bfd_mach_o_asymbol));
3af9a47b
NC
1599
1600 if (sym->symbols == NULL)
1601 {
1602 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbols: unable to allocate memory for symbols\n");
a95a4550 1603 return -1;
3af9a47b 1604 }
a95a4550 1605
3af9a47b
NC
1606 ret = bfd_mach_o_scan_read_symtab_strtab (abfd, sym);
1607 if (ret != 0)
1608 return ret;
1609
1610 for (i = 0; i < sym->nsyms; i++)
1611 {
1612 ret = bfd_mach_o_scan_read_symtab_symbol (abfd, sym, &sym->symbols[i], i);
1613 if (ret != 0)
1614 return ret;
1615 }
a95a4550 1616
3af9a47b
NC
1617 return 0;
1618}
1619
1620int
116c20d2
NC
1621bfd_mach_o_scan_read_dysymtab_symbol (bfd *abfd,
1622 bfd_mach_o_dysymtab_command *dysym,
1623 bfd_mach_o_symtab_command *sym,
92bc0e80 1624 bfd_mach_o_asymbol *s,
116c20d2 1625 unsigned long i)
3af9a47b
NC
1626{
1627 unsigned long isymoff = dysym->indirectsymoff + (i * 4);
1628 unsigned long symindex;
1629 unsigned char buf[4];
1630
1631 BFD_ASSERT (i < dysym->nindirectsyms);
a95a4550 1632
c2f09c75
TG
1633 if (bfd_seek (abfd, isymoff, SEEK_SET) != 0
1634 || bfd_bread ((PTR) buf, 4, abfd) != 4)
3af9a47b
NC
1635 {
1636 fprintf (stderr, "bfd_mach_o_scan_read_dysymtab_symbol: unable to read %lu bytes at %lu\n",
1637 (unsigned long) 4, isymoff);
1638 return -1;
1639 }
1640 symindex = bfd_h_get_32 (abfd, buf);
a95a4550 1641
3af9a47b
NC
1642 return bfd_mach_o_scan_read_symtab_symbol (abfd, sym, s, symindex);
1643}
1644
1645static const char *
116c20d2 1646bfd_mach_o_i386_flavour_string (unsigned int flavour)
3af9a47b
NC
1647{
1648 switch ((int) flavour)
1649 {
15e1c58a
TG
1650 case BFD_MACH_O_x86_THREAD_STATE32: return "x86_THREAD_STATE32";
1651 case BFD_MACH_O_x86_FLOAT_STATE32: return "x86_FLOAT_STATE32";
1652 case BFD_MACH_O_x86_EXCEPTION_STATE32: return "x86_EXCEPTION_STATE32";
1653 case BFD_MACH_O_x86_THREAD_STATE64: return "x86_THREAD_STATE64";
1654 case BFD_MACH_O_x86_FLOAT_STATE64: return "x86_FLOAT_STATE64";
1655 case BFD_MACH_O_x86_EXCEPTION_STATE64: return "x86_EXCEPTION_STATE64";
1656 case BFD_MACH_O_x86_THREAD_STATE: return "x86_THREAD_STATE";
1657 case BFD_MACH_O_x86_FLOAT_STATE: return "x86_FLOAT_STATE";
1658 case BFD_MACH_O_x86_EXCEPTION_STATE: return "x86_EXCEPTION_STATE";
1659 case BFD_MACH_O_x86_DEBUG_STATE32: return "x86_DEBUG_STATE32";
1660 case BFD_MACH_O_x86_DEBUG_STATE64: return "x86_DEBUG_STATE64";
1661 case BFD_MACH_O_x86_DEBUG_STATE: return "x86_DEBUG_STATE";
1662 case BFD_MACH_O_THREAD_STATE_NONE: return "THREAD_STATE_NONE";
3af9a47b
NC
1663 default: return "UNKNOWN";
1664 }
1665}
1666
1667static const char *
116c20d2 1668bfd_mach_o_ppc_flavour_string (unsigned int flavour)
3af9a47b
NC
1669{
1670 switch ((int) flavour)
1671 {
1672 case BFD_MACH_O_PPC_THREAD_STATE: return "PPC_THREAD_STATE";
1673 case BFD_MACH_O_PPC_FLOAT_STATE: return "PPC_FLOAT_STATE";
1674 case BFD_MACH_O_PPC_EXCEPTION_STATE: return "PPC_EXCEPTION_STATE";
1675 case BFD_MACH_O_PPC_VECTOR_STATE: return "PPC_VECTOR_STATE";
1676 default: return "UNKNOWN";
1677 }
1678}
1679
1680static int
116c20d2
NC
1681bfd_mach_o_scan_read_dylinker (bfd *abfd,
1682 bfd_mach_o_load_command *command)
3af9a47b
NC
1683{
1684 bfd_mach_o_dylinker_command *cmd = &command->command.dylinker;
1685 unsigned char buf[4];
1686 unsigned int nameoff;
1687 asection *bfdsec;
1688 char *sname;
1689 const char *prefix;
1690
1691 BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLINKER)
1692 || (command->type == BFD_MACH_O_LC_LOAD_DYLINKER));
1693
c2f09c75
TG
1694 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
1695 || bfd_bread ((PTR) buf, 4, abfd) != 4)
3af9a47b
NC
1696 return -1;
1697
1698 nameoff = bfd_h_get_32 (abfd, buf + 0);
1699
1700 cmd->name_offset = command->offset + nameoff;
1701 cmd->name_len = command->len - nameoff;
1702
1703 if (command->type == BFD_MACH_O_LC_LOAD_DYLINKER)
1704 prefix = "LC_LOAD_DYLINKER";
1705 else if (command->type == BFD_MACH_O_LC_ID_DYLINKER)
1706 prefix = "LC_ID_DYLINKER";
1707 else
1708 abort ();
1709
116c20d2 1710 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
1711 if (sname == NULL)
1712 return -1;
1713 strcpy (sname, prefix);
1714
117ed4f8 1715 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
3af9a47b
NC
1716 if (bfdsec == NULL)
1717 return -1;
a95a4550 1718
3af9a47b
NC
1719 bfdsec->vma = 0;
1720 bfdsec->lma = 0;
846b9259
TG
1721 bfdsec->size = command->len - nameoff;
1722 bfdsec->filepos = command->offset + nameoff;
3af9a47b 1723 bfdsec->alignment_power = 0;
3af9a47b
NC
1724
1725 cmd->section = bfdsec;
1726
1727 return 0;
1728}
1729
1730static int
116c20d2 1731bfd_mach_o_scan_read_dylib (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1732{
1733 bfd_mach_o_dylib_command *cmd = &command->command.dylib;
1734 unsigned char buf[16];
1735 unsigned int nameoff;
1736 asection *bfdsec;
1737 char *sname;
1738 const char *prefix;
1739
1740 BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLIB)
1741 || (command->type == BFD_MACH_O_LC_LOAD_DYLIB)
1742 || (command->type == BFD_MACH_O_LC_LOAD_WEAK_DYLIB));
1743
c2f09c75
TG
1744 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
1745 || bfd_bread ((PTR) buf, 16, abfd) != 16)
3af9a47b
NC
1746 return -1;
1747
1748 nameoff = bfd_h_get_32 (abfd, buf + 0);
1749 cmd->timestamp = bfd_h_get_32 (abfd, buf + 4);
1750 cmd->current_version = bfd_h_get_32 (abfd, buf + 8);
1751 cmd->compatibility_version = bfd_h_get_32 (abfd, buf + 12);
1752
1753 cmd->name_offset = command->offset + nameoff;
1754 cmd->name_len = command->len - nameoff;
1755
1756 if (command->type == BFD_MACH_O_LC_LOAD_DYLIB)
1757 prefix = "LC_LOAD_DYLIB";
1758 else if (command->type == BFD_MACH_O_LC_LOAD_WEAK_DYLIB)
1759 prefix = "LC_LOAD_WEAK_DYLIB";
1760 else if (command->type == BFD_MACH_O_LC_ID_DYLIB)
1761 prefix = "LC_ID_DYLIB";
1762 else
1763 abort ();
1764
116c20d2 1765 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
1766 if (sname == NULL)
1767 return -1;
1768 strcpy (sname, prefix);
1769
117ed4f8 1770 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
3af9a47b
NC
1771 if (bfdsec == NULL)
1772 return -1;
a95a4550 1773
3af9a47b
NC
1774 bfdsec->vma = 0;
1775 bfdsec->lma = 0;
eea6121a 1776 bfdsec->size = command->len - 8;
3af9a47b
NC
1777 bfdsec->filepos = command->offset + 8;
1778 bfdsec->alignment_power = 0;
3af9a47b
NC
1779
1780 cmd->section = bfdsec;
1781
1782 return 0;
1783}
1784
1785static int
116c20d2
NC
1786bfd_mach_o_scan_read_prebound_dylib (bfd *abfd ATTRIBUTE_UNUSED,
1787 bfd_mach_o_load_command *command ATTRIBUTE_UNUSED)
3af9a47b
NC
1788{
1789 /* bfd_mach_o_prebound_dylib_command *cmd = &command->command.prebound_dylib; */
1790
1791 BFD_ASSERT (command->type == BFD_MACH_O_LC_PREBOUND_DYLIB);
1792 return 0;
1793}
1794
1795static int
116c20d2 1796bfd_mach_o_scan_read_thread (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1797{
1798 bfd_mach_o_data_struct *mdata = NULL;
1799 bfd_mach_o_thread_command *cmd = &command->command.thread;
1800 unsigned char buf[8];
92bc0e80 1801 unsigned int offset;
3af9a47b
NC
1802 unsigned int nflavours;
1803 unsigned int i;
1804
1805 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
1806 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
1807
1808 BFD_ASSERT (bfd_mach_o_valid (abfd));
1809 mdata = abfd->tdata.mach_o_data;
a95a4550 1810
3af9a47b
NC
1811 offset = 8;
1812 nflavours = 0;
1813 while (offset != command->len)
1814 {
1815 if (offset >= command->len)
1816 return -1;
1817
c2f09c75
TG
1818 if (bfd_seek (abfd, command->offset + offset, SEEK_SET) != 0
1819 || bfd_bread ((PTR) buf, 8, abfd) != 8)
3af9a47b
NC
1820 return -1;
1821
1822 offset += 8 + bfd_h_get_32 (abfd, buf + 4) * 4;
1823 nflavours++;
1824 }
1825
116c20d2 1826 cmd->flavours = bfd_alloc (abfd, nflavours * sizeof (bfd_mach_o_thread_flavour));
3af9a47b
NC
1827 if (cmd->flavours == NULL)
1828 return -1;
1829 cmd->nflavours = nflavours;
1830
1831 offset = 8;
1832 nflavours = 0;
1833 while (offset != command->len)
1834 {
1835 if (offset >= command->len)
1836 return -1;
1837
1838 if (nflavours >= cmd->nflavours)
1839 return -1;
1840
c2f09c75
TG
1841 if (bfd_seek (abfd, command->offset + offset, SEEK_SET) != 0
1842 || bfd_bread ((PTR) buf, 8, abfd) != 8)
3af9a47b
NC
1843 return -1;
1844
1845 cmd->flavours[nflavours].flavour = bfd_h_get_32 (abfd, buf);
1846 cmd->flavours[nflavours].offset = command->offset + offset + 8;
1847 cmd->flavours[nflavours].size = bfd_h_get_32 (abfd, buf + 4) * 4;
1848 offset += cmd->flavours[nflavours].size + 8;
1849 nflavours++;
1850 }
1851
1852 for (i = 0; i < nflavours; i++)
1853 {
1854 asection *bfdsec;
1855 unsigned int snamelen;
1856 char *sname;
1857 const char *flavourstr;
1858 const char *prefix = "LC_THREAD";
a95a4550
AM
1859 unsigned int j = 0;
1860
3af9a47b
NC
1861 switch (mdata->header.cputype)
1862 {
1863 case BFD_MACH_O_CPU_TYPE_POWERPC:
1e8a024a 1864 case BFD_MACH_O_CPU_TYPE_POWERPC_64:
3af9a47b
NC
1865 flavourstr = bfd_mach_o_ppc_flavour_string (cmd->flavours[i].flavour);
1866 break;
1867 case BFD_MACH_O_CPU_TYPE_I386:
1e8a024a 1868 case BFD_MACH_O_CPU_TYPE_X86_64:
3af9a47b
NC
1869 flavourstr = bfd_mach_o_i386_flavour_string (cmd->flavours[i].flavour);
1870 break;
1871 default:
1872 flavourstr = "UNKNOWN_ARCHITECTURE";
1873 break;
1874 }
a95a4550 1875
3af9a47b 1876 snamelen = strlen (prefix) + 1 + 20 + 1 + strlen (flavourstr) + 1;
116c20d2 1877 sname = bfd_alloc (abfd, snamelen);
3af9a47b
NC
1878 if (sname == NULL)
1879 return -1;
1880
1881 for (;;)
1882 {
a95a4550
AM
1883 sprintf (sname, "%s.%s.%u", prefix, flavourstr, j);
1884 if (bfd_get_section_by_name (abfd, sname) == NULL)
3af9a47b 1885 break;
a95a4550 1886 j++;
3af9a47b
NC
1887 }
1888
117ed4f8 1889 bfdsec = bfd_make_section_with_flags (abfd, sname, SEC_HAS_CONTENTS);
a95a4550 1890
3af9a47b
NC
1891 bfdsec->vma = 0;
1892 bfdsec->lma = 0;
eea6121a 1893 bfdsec->size = cmd->flavours[i].size;
3af9a47b
NC
1894 bfdsec->filepos = cmd->flavours[i].offset;
1895 bfdsec->alignment_power = 0x0;
3af9a47b
NC
1896
1897 cmd->section = bfdsec;
1898 }
1899
1900 return 0;
1901}
1902
a95a4550 1903static int
116c20d2 1904bfd_mach_o_scan_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1905{
1906 bfd_mach_o_dysymtab_command *seg = &command->command.dysymtab;
1907 unsigned char buf[72];
1908
1909 BFD_ASSERT (command->type == BFD_MACH_O_LC_DYSYMTAB);
1910
c2f09c75
TG
1911 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
1912 || bfd_bread ((PTR) buf, 72, abfd) != 72)
3af9a47b
NC
1913 return -1;
1914
1915 seg->ilocalsym = bfd_h_get_32 (abfd, buf + 0);
1916 seg->nlocalsym = bfd_h_get_32 (abfd, buf + 4);
1917 seg->iextdefsym = bfd_h_get_32 (abfd, buf + 8);
1918 seg->nextdefsym = bfd_h_get_32 (abfd, buf + 12);
1919 seg->iundefsym = bfd_h_get_32 (abfd, buf + 16);
1920 seg->nundefsym = bfd_h_get_32 (abfd, buf + 20);
1921 seg->tocoff = bfd_h_get_32 (abfd, buf + 24);
1922 seg->ntoc = bfd_h_get_32 (abfd, buf + 28);
1923 seg->modtaboff = bfd_h_get_32 (abfd, buf + 32);
1924 seg->nmodtab = bfd_h_get_32 (abfd, buf + 36);
1925 seg->extrefsymoff = bfd_h_get_32 (abfd, buf + 40);
1926 seg->nextrefsyms = bfd_h_get_32 (abfd, buf + 44);
1927 seg->indirectsymoff = bfd_h_get_32 (abfd, buf + 48);
1928 seg->nindirectsyms = bfd_h_get_32 (abfd, buf + 52);
1929 seg->extreloff = bfd_h_get_32 (abfd, buf + 56);
1930 seg->nextrel = bfd_h_get_32 (abfd, buf + 60);
1931 seg->locreloff = bfd_h_get_32 (abfd, buf + 64);
1932 seg->nlocrel = bfd_h_get_32 (abfd, buf + 68);
1933
1934 return 0;
1935}
1936
a95a4550 1937static int
116c20d2 1938bfd_mach_o_scan_read_symtab (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1939{
1940 bfd_mach_o_symtab_command *seg = &command->command.symtab;
1941 unsigned char buf[16];
3af9a47b
NC
1942
1943 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
1944
c2f09c75
TG
1945 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
1946 || bfd_bread ((PTR) buf, 16, abfd) != 16)
3af9a47b 1947 return -1;
a95a4550 1948
3af9a47b
NC
1949 seg->symoff = bfd_h_get_32 (abfd, buf);
1950 seg->nsyms = bfd_h_get_32 (abfd, buf + 4);
1951 seg->stroff = bfd_h_get_32 (abfd, buf + 8);
1952 seg->strsize = bfd_h_get_32 (abfd, buf + 12);
1953 seg->symbols = NULL;
1954 seg->strtab = NULL;
1955
15e1c58a
TG
1956 if (seg->nsyms != 0)
1957 abfd->flags |= HAS_SYMS;
1958
3af9a47b
NC
1959 return 0;
1960}
1961
15e1c58a
TG
1962static int
1963bfd_mach_o_scan_read_uuid (bfd *abfd, bfd_mach_o_load_command *command)
1964{
1965 bfd_mach_o_uuid_command *cmd = &command->command.uuid;
1966 asection *bfdsec;
1967 char *sname;
1968 static const char prefix[] = "LC_UUID";
1969
1970 BFD_ASSERT (command->type == BFD_MACH_O_LC_UUID);
1971
c2f09c75
TG
1972 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
1973 || bfd_bread ((PTR) cmd->uuid, 16, abfd) != 16)
15e1c58a
TG
1974 return -1;
1975
1976 sname = bfd_alloc (abfd, strlen (prefix) + 1);
1977 if (sname == NULL)
1978 return -1;
1979 strcpy (sname, prefix);
1980
1981 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
1982 if (bfdsec == NULL)
1983 return -1;
1984
1985 bfdsec->vma = 0;
1986 bfdsec->lma = 0;
1987 bfdsec->size = command->len - 8;
1988 bfdsec->filepos = command->offset + 8;
1989 bfdsec->alignment_power = 0;
1990
1991 cmd->section = bfdsec;
1992
1993 return 0;
1994}
1995
3af9a47b 1996static int
1e8a024a
TG
1997bfd_mach_o_scan_read_segment (bfd *abfd,
1998 bfd_mach_o_load_command *command,
1999 unsigned int wide)
3af9a47b 2000{
1e8a024a 2001 unsigned char buf[64];
3af9a47b
NC
2002 bfd_mach_o_segment_command *seg = &command->command.segment;
2003 unsigned long i;
a95a4550 2004
1e8a024a
TG
2005 if (wide)
2006 {
2007 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT_64);
3af9a47b 2008
c2f09c75
TG
2009 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
2010 || bfd_bread ((PTR) buf, 64, abfd) != 64)
1e8a024a 2011 return -1;
3af9a47b 2012
1e8a024a 2013 memcpy (seg->segname, buf, 16);
15e1c58a 2014 seg->segname[16] = '\0';
1e8a024a
TG
2015
2016 seg->vmaddr = bfd_h_get_64 (abfd, buf + 16);
2017 seg->vmsize = bfd_h_get_64 (abfd, buf + 24);
2018 seg->fileoff = bfd_h_get_64 (abfd, buf + 32);
2019 seg->filesize = bfd_h_get_64 (abfd, buf + 40);
2020 seg->maxprot = bfd_h_get_32 (abfd, buf + 48);
2021 seg->initprot = bfd_h_get_32 (abfd, buf + 52);
2022 seg->nsects = bfd_h_get_32 (abfd, buf + 56);
2023 seg->flags = bfd_h_get_32 (abfd, buf + 60);
2024 }
2025 else
2026 {
2027 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
2028
c2f09c75
TG
2029 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
2030 || bfd_bread ((PTR) buf, 48, abfd) != 48)
1e8a024a
TG
2031 return -1;
2032
2033 memcpy (seg->segname, buf, 16);
15e1c58a 2034 seg->segname[16] = '\0';
1e8a024a
TG
2035
2036 seg->vmaddr = bfd_h_get_32 (abfd, buf + 16);
2037 seg->vmsize = bfd_h_get_32 (abfd, buf + 20);
2038 seg->fileoff = bfd_h_get_32 (abfd, buf + 24);
2039 seg->filesize = bfd_h_get_32 (abfd, buf + 28);
2040 seg->maxprot = bfd_h_get_32 (abfd, buf + 32);
2041 seg->initprot = bfd_h_get_32 (abfd, buf + 36);
2042 seg->nsects = bfd_h_get_32 (abfd, buf + 40);
2043 seg->flags = bfd_h_get_32 (abfd, buf + 44);
2044 }
3af9a47b 2045
3af9a47b
NC
2046 if (seg->nsects != 0)
2047 {
154a1ee5
TG
2048 seg->sections = bfd_alloc (abfd, seg->nsects
2049 * sizeof (bfd_mach_o_section));
3af9a47b
NC
2050 if (seg->sections == NULL)
2051 return -1;
a95a4550 2052
3af9a47b
NC
2053 for (i = 0; i < seg->nsects; i++)
2054 {
1e8a024a 2055 bfd_vma segoff;
154a1ee5 2056 if (wide)
c2f09c75 2057 segoff = command->offset + BFD_MACH_O_LC_SEGMENT_64_SIZE
154a1ee5
TG
2058 + (i * BFD_MACH_O_SECTION_64_SIZE);
2059 else
c2f09c75 2060 segoff = command->offset + BFD_MACH_O_LC_SEGMENT_SIZE
154a1ee5 2061 + (i * BFD_MACH_O_SECTION_SIZE);
3af9a47b 2062
1e8a024a 2063 if (bfd_mach_o_scan_read_section
15e1c58a 2064 (abfd, &seg->sections[i], segoff, seg->initprot, wide) != 0)
3af9a47b 2065 return -1;
a95a4550 2066 }
3af9a47b
NC
2067 }
2068
2069 return 0;
2070}
2071
1e8a024a
TG
2072static int
2073bfd_mach_o_scan_read_segment_32 (bfd *abfd, bfd_mach_o_load_command *command)
2074{
2075 return bfd_mach_o_scan_read_segment (abfd, command, 0);
2076}
2077
2078static int
2079bfd_mach_o_scan_read_segment_64 (bfd *abfd, bfd_mach_o_load_command *command)
2080{
2081 return bfd_mach_o_scan_read_segment (abfd, command, 1);
2082}
2083
3af9a47b 2084static int
116c20d2 2085bfd_mach_o_scan_read_command (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
2086{
2087 unsigned char buf[8];
2088
c2f09c75
TG
2089 if (bfd_seek (abfd, command->offset, SEEK_SET) != 0
2090 || bfd_bread ((PTR) buf, 8, abfd) != 8)
3af9a47b
NC
2091 return -1;
2092
154a1ee5 2093 command->type = bfd_h_get_32 (abfd, buf) & ~BFD_MACH_O_LC_REQ_DYLD;
e84d6fca 2094 command->type_required = (bfd_h_get_32 (abfd, buf) & BFD_MACH_O_LC_REQ_DYLD
154a1ee5 2095 ? TRUE : FALSE);
3af9a47b
NC
2096 command->len = bfd_h_get_32 (abfd, buf + 4);
2097
2098 switch (command->type)
2099 {
2100 case BFD_MACH_O_LC_SEGMENT:
1e8a024a
TG
2101 if (bfd_mach_o_scan_read_segment_32 (abfd, command) != 0)
2102 return -1;
2103 break;
2104 case BFD_MACH_O_LC_SEGMENT_64:
2105 if (bfd_mach_o_scan_read_segment_64 (abfd, command) != 0)
3af9a47b
NC
2106 return -1;
2107 break;
2108 case BFD_MACH_O_LC_SYMTAB:
2109 if (bfd_mach_o_scan_read_symtab (abfd, command) != 0)
2110 return -1;
2111 break;
2112 case BFD_MACH_O_LC_SYMSEG:
2113 break;
2114 case BFD_MACH_O_LC_THREAD:
2115 case BFD_MACH_O_LC_UNIXTHREAD:
2116 if (bfd_mach_o_scan_read_thread (abfd, command) != 0)
2117 return -1;
2118 break;
2119 case BFD_MACH_O_LC_LOAD_DYLINKER:
2120 case BFD_MACH_O_LC_ID_DYLINKER:
2121 if (bfd_mach_o_scan_read_dylinker (abfd, command) != 0)
2122 return -1;
2123 break;
2124 case BFD_MACH_O_LC_LOAD_DYLIB:
2125 case BFD_MACH_O_LC_ID_DYLIB:
2126 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
2127 if (bfd_mach_o_scan_read_dylib (abfd, command) != 0)
2128 return -1;
2129 break;
2130 case BFD_MACH_O_LC_PREBOUND_DYLIB:
2131 if (bfd_mach_o_scan_read_prebound_dylib (abfd, command) != 0)
2132 return -1;
2133 break;
2134 case BFD_MACH_O_LC_LOADFVMLIB:
2135 case BFD_MACH_O_LC_IDFVMLIB:
2136 case BFD_MACH_O_LC_IDENT:
2137 case BFD_MACH_O_LC_FVMFILE:
2138 case BFD_MACH_O_LC_PREPAGE:
2139 case BFD_MACH_O_LC_ROUTINES:
2140 case BFD_MACH_O_LC_SUB_FRAMEWORK:
2141 break;
2142 case BFD_MACH_O_LC_DYSYMTAB:
2143 if (bfd_mach_o_scan_read_dysymtab (abfd, command) != 0)
2144 return -1;
2145 break;
2146 case BFD_MACH_O_LC_SUB_UMBRELLA:
2147 case BFD_MACH_O_LC_SUB_CLIENT:
2148 case BFD_MACH_O_LC_SUB_LIBRARY:
2149 case BFD_MACH_O_LC_TWOLEVEL_HINTS:
2150 case BFD_MACH_O_LC_PREBIND_CKSUM:
2151 break;
15e1c58a
TG
2152 case BFD_MACH_O_LC_UUID:
2153 if (bfd_mach_o_scan_read_uuid (abfd, command) != 0)
2154 return -1;
2155 break;
2156 case BFD_MACH_O_LC_CODE_SIGNATURE:
846b9259
TG
2157 case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO:
2158 case BFD_MACH_O_LC_REEXPORT_DYLIB:
15e1c58a 2159 break;
3af9a47b
NC
2160 default:
2161 fprintf (stderr, "unable to read unknown load command 0x%lx\n",
2162 (unsigned long) command->type);
2163 break;
2164 }
2165
2166 return 0;
2167}
2168
2169static void
116c20d2 2170bfd_mach_o_flatten_sections (bfd *abfd)
3af9a47b
NC
2171{
2172 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
2173 long csect = 0;
2174 unsigned long i, j;
a95a4550 2175
15e1c58a 2176 /* Count total number of sections. */
3af9a47b
NC
2177 mdata->nsects = 0;
2178
2179 for (i = 0; i < mdata->header.ncmds; i++)
2180 {
1e8a024a
TG
2181 if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT
2182 || mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT_64)
3af9a47b 2183 {
e84d6fca
AM
2184 bfd_mach_o_segment_command *seg;
2185
2186 seg = &mdata->commands[i].command.segment;
3af9a47b
NC
2187 mdata->nsects += seg->nsects;
2188 }
2189 }
2190
15e1c58a 2191 /* Allocate sections array. */
e84d6fca
AM
2192 mdata->sections = bfd_alloc (abfd,
2193 mdata->nsects * sizeof (bfd_mach_o_section *));
15e1c58a
TG
2194
2195 /* Fill the array. */
3af9a47b
NC
2196 csect = 0;
2197
2198 for (i = 0; i < mdata->header.ncmds; i++)
2199 {
1e8a024a
TG
2200 if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT
2201 || mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT_64)
3af9a47b 2202 {
e84d6fca 2203 bfd_mach_o_segment_command *seg;
3af9a47b 2204
e84d6fca 2205 seg = &mdata->commands[i].command.segment;
3af9a47b
NC
2206 BFD_ASSERT (csect + seg->nsects <= mdata->nsects);
2207
2208 for (j = 0; j < seg->nsects; j++)
2209 mdata->sections[csect++] = &seg->sections[j];
2210 }
2211 }
2212}
2213
2214int
116c20d2 2215bfd_mach_o_scan_start_address (bfd *abfd)
3af9a47b
NC
2216{
2217 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
2218 bfd_mach_o_thread_command *cmd = NULL;
2219 unsigned long i;
2220
2221 for (i = 0; i < mdata->header.ncmds; i++)
2222 {
2223 if ((mdata->commands[i].type == BFD_MACH_O_LC_THREAD) ||
2224 (mdata->commands[i].type == BFD_MACH_O_LC_UNIXTHREAD))
2225 {
2226 if (cmd == NULL)
2227 cmd = &mdata->commands[i].command.thread;
2228 else
2229 return 0;
2230 }
2231 }
2232
2233 if (cmd == NULL)
2234 return 0;
2235
2236 for (i = 0; i < cmd->nflavours; i++)
2237 {
a95a4550 2238 if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_I386)
e84d6fca 2239 && (cmd->flavours[i].flavour
15e1c58a 2240 == (unsigned long) BFD_MACH_O_x86_THREAD_STATE32))
3af9a47b
NC
2241 {
2242 unsigned char buf[4];
2243
c2f09c75
TG
2244 if (bfd_seek (abfd, cmd->flavours[i].offset + 40, SEEK_SET) != 0
2245 || bfd_bread (buf, 4, abfd) != 4)
3af9a47b
NC
2246 return -1;
2247
2248 abfd->start_address = bfd_h_get_32 (abfd, buf);
2249 }
a95a4550 2250 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC)
3af9a47b
NC
2251 && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE))
2252 {
2253 unsigned char buf[4];
2254
c2f09c75
TG
2255 if (bfd_seek (abfd, cmd->flavours[i].offset + 0, SEEK_SET) != 0
2256 || bfd_bread (buf, 4, abfd) != 4)
3af9a47b
NC
2257 return -1;
2258
2259 abfd->start_address = bfd_h_get_32 (abfd, buf);
2260 }
1e8a024a
TG
2261 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC_64)
2262 && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE_64))
2263 {
2264 unsigned char buf[8];
2265
c2f09c75
TG
2266 if (bfd_seek (abfd, cmd->flavours[i].offset + 0, SEEK_SET) != 0
2267 || bfd_bread (buf, 8, abfd) != 8)
1e8a024a
TG
2268 return -1;
2269
2270 abfd->start_address = bfd_h_get_64 (abfd, buf);
2271 }
2272 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_X86_64)
2273 && (cmd->flavours[i].flavour == BFD_MACH_O_x86_THREAD_STATE64))
2274 {
2275 unsigned char buf[8];
2276
c2f09c75
TG
2277 if (bfd_seek (abfd, cmd->flavours[i].offset + (16 * 8), SEEK_SET) != 0
2278 || bfd_bread (buf, 8, abfd) != 8)
1e8a024a
TG
2279 return -1;
2280
2281 abfd->start_address = bfd_h_get_64 (abfd, buf);
2282 }
3af9a47b
NC
2283 }
2284
2285 return 0;
2286}
2287
2288int
116c20d2
NC
2289bfd_mach_o_scan (bfd *abfd,
2290 bfd_mach_o_header *header,
2291 bfd_mach_o_data_struct *mdata)
3af9a47b
NC
2292{
2293 unsigned int i;
3af9a47b
NC
2294 enum bfd_architecture cputype;
2295 unsigned long cpusubtype;
1e8a024a
TG
2296 unsigned int hdrsize;
2297
c2f09c75 2298 hdrsize = mach_o_wide_p (header) ?
154a1ee5 2299 BFD_MACH_O_HEADER_64_SIZE : BFD_MACH_O_HEADER_SIZE;
3af9a47b 2300
3af9a47b 2301 mdata->header = *header;
3af9a47b 2302
154a1ee5 2303 abfd->flags = abfd->flags & BFD_IN_MEMORY;
15e1c58a
TG
2304 switch (header->filetype)
2305 {
2306 case BFD_MACH_O_MH_OBJECT:
2307 abfd->flags |= HAS_RELOC;
2308 break;
2309 case BFD_MACH_O_MH_EXECUTE:
2310 abfd->flags |= EXEC_P;
2311 break;
2312 case BFD_MACH_O_MH_DYLIB:
2313 case BFD_MACH_O_MH_BUNDLE:
2314 abfd->flags |= DYNAMIC;
2315 break;
2316 }
2317
3af9a47b
NC
2318 abfd->tdata.mach_o_data = mdata;
2319
e84d6fca
AM
2320 bfd_mach_o_convert_architecture (header->cputype, header->cpusubtype,
2321 &cputype, &cpusubtype);
3af9a47b
NC
2322 if (cputype == bfd_arch_unknown)
2323 {
2324 fprintf (stderr, "bfd_mach_o_scan: unknown architecture 0x%lx/0x%lx\n",
2325 header->cputype, header->cpusubtype);
2326 return -1;
2327 }
2328
2329 bfd_set_arch_mach (abfd, cputype, cpusubtype);
a95a4550 2330
3af9a47b
NC
2331 if (header->ncmds != 0)
2332 {
116c20d2 2333 mdata->commands = bfd_alloc (abfd, header->ncmds * sizeof (bfd_mach_o_load_command));
3af9a47b
NC
2334 if (mdata->commands == NULL)
2335 return -1;
a95a4550 2336
3af9a47b
NC
2337 for (i = 0; i < header->ncmds; i++)
2338 {
2339 bfd_mach_o_load_command *cur = &mdata->commands[i];
2340
2341 if (i == 0)
1e8a024a 2342 cur->offset = hdrsize;
3af9a47b
NC
2343 else
2344 {
2345 bfd_mach_o_load_command *prev = &mdata->commands[i - 1];
2346 cur->offset = prev->offset + prev->len;
2347 }
2348
2349 if (bfd_mach_o_scan_read_command (abfd, cur) < 0)
2350 return -1;
a95a4550 2351 }
3af9a47b
NC
2352 }
2353
2354 if (bfd_mach_o_scan_start_address (abfd) < 0)
7e3102a7 2355 return -1;
3af9a47b
NC
2356
2357 bfd_mach_o_flatten_sections (abfd);
3af9a47b
NC
2358 return 0;
2359}
2360
b34976b6 2361bfd_boolean
154a1ee5 2362bfd_mach_o_mkobject_init (bfd *abfd)
3af9a47b
NC
2363{
2364 bfd_mach_o_data_struct *mdata = NULL;
2365
116c20d2 2366 mdata = bfd_alloc (abfd, sizeof (bfd_mach_o_data_struct));
3af9a47b 2367 if (mdata == NULL)
b34976b6 2368 return FALSE;
3af9a47b
NC
2369 abfd->tdata.mach_o_data = mdata;
2370
2371 mdata->header.magic = 0;
2372 mdata->header.cputype = 0;
2373 mdata->header.cpusubtype = 0;
2374 mdata->header.filetype = 0;
2375 mdata->header.ncmds = 0;
2376 mdata->header.sizeofcmds = 0;
2377 mdata->header.flags = 0;
2378 mdata->header.byteorder = BFD_ENDIAN_UNKNOWN;
2379 mdata->commands = NULL;
3af9a47b
NC
2380 mdata->nsects = 0;
2381 mdata->sections = NULL;
3af9a47b 2382
b34976b6 2383 return TRUE;
3af9a47b
NC
2384}
2385
2386const bfd_target *
154a1ee5
TG
2387bfd_mach_o_header_p (bfd *abfd,
2388 bfd_mach_o_filetype filetype,
2389 bfd_mach_o_cpu_type cputype)
3af9a47b 2390{
e84d6fca 2391 struct bfd_preserve preserve;
3af9a47b
NC
2392 bfd_mach_o_header header;
2393
e84d6fca 2394 preserve.marker = NULL;
154a1ee5 2395 if (!bfd_mach_o_read_header (abfd, &header))
e84d6fca 2396 goto wrong;
3af9a47b 2397
e84d6fca
AM
2398 if (! (header.byteorder == BFD_ENDIAN_BIG
2399 || header.byteorder == BFD_ENDIAN_LITTLE))
3af9a47b 2400 {
e84d6fca 2401 fprintf (stderr, "unknown header byte-order value 0x%lx\n",
0af1713e 2402 (unsigned long) header.byteorder);
e84d6fca 2403 goto wrong;
3af9a47b
NC
2404 }
2405
e84d6fca
AM
2406 if (! ((header.byteorder == BFD_ENDIAN_BIG
2407 && abfd->xvec->byteorder == BFD_ENDIAN_BIG
2408 && abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
2409 || (header.byteorder == BFD_ENDIAN_LITTLE
2410 && abfd->xvec->byteorder == BFD_ENDIAN_LITTLE
2411 && abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)))
2412 goto wrong;
3af9a47b 2413
154a1ee5
TG
2414 /* Check cputype and filetype.
2415 In case of wildcard, do not accept magics that are handled by existing
2416 targets. */
2417 if (cputype)
2418 {
2419 if (header.cputype != cputype)
2420 goto wrong;
2421 }
2422 else
2423 {
2424 switch (header.cputype)
2425 {
2426 case BFD_MACH_O_CPU_TYPE_I386:
2427 /* Handled by mach-o-i386 */
2428 goto wrong;
2429 default:
2430 break;
2431 }
2432 }
2433 if (filetype)
2434 {
2435 if (header.filetype != filetype)
2436 goto wrong;
2437 }
2438 else
2439 {
2440 switch (header.filetype)
2441 {
2442 case BFD_MACH_O_MH_CORE:
2443 /* Handled by core_p */
2444 goto wrong;
2445 default:
2446 break;
2447 }
2448 }
2449
e84d6fca
AM
2450 preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct));
2451 if (preserve.marker == NULL
2452 || !bfd_preserve_save (abfd, &preserve))
2453 goto fail;
3af9a47b 2454
e84d6fca
AM
2455 if (bfd_mach_o_scan (abfd, &header,
2456 (bfd_mach_o_data_struct *) preserve.marker) != 0)
2457 goto wrong;
a95a4550 2458
e84d6fca 2459 bfd_preserve_finish (abfd, &preserve);
3af9a47b 2460 return abfd->xvec;
e84d6fca
AM
2461
2462 wrong:
2463 bfd_set_error (bfd_error_wrong_format);
2464
2465 fail:
2466 if (preserve.marker != NULL)
2467 bfd_preserve_restore (abfd, &preserve);
2468 return NULL;
3af9a47b
NC
2469}
2470
154a1ee5
TG
2471static const bfd_target *
2472bfd_mach_o_gen_object_p (bfd *abfd)
3af9a47b 2473{
154a1ee5
TG
2474 return bfd_mach_o_header_p (abfd, 0, 0);
2475}
e84d6fca 2476
154a1ee5
TG
2477static const bfd_target *
2478bfd_mach_o_gen_core_p (bfd *abfd)
2479{
2480 return bfd_mach_o_header_p (abfd, BFD_MACH_O_MH_CORE, 0);
3af9a47b
NC
2481}
2482
2483typedef struct mach_o_fat_archentry
2484{
2485 unsigned long cputype;
2486 unsigned long cpusubtype;
2487 unsigned long offset;
2488 unsigned long size;
2489 unsigned long align;
3af9a47b
NC
2490} mach_o_fat_archentry;
2491
2492typedef struct mach_o_fat_data_struct
2493{
2494 unsigned long magic;
2495 unsigned long nfat_arch;
2496 mach_o_fat_archentry *archentries;
2497} mach_o_fat_data_struct;
2498
2499const bfd_target *
116c20d2 2500bfd_mach_o_archive_p (bfd *abfd)
3af9a47b 2501{
e84d6fca 2502 mach_o_fat_data_struct *adata = NULL;
3af9a47b
NC
2503 unsigned char buf[20];
2504 unsigned long i;
2505
c2f09c75
TG
2506 if (bfd_seek (abfd, 0, SEEK_SET) != 0
2507 || bfd_bread ((PTR) buf, 8, abfd) != 8)
e84d6fca 2508 goto error;
3af9a47b 2509
116c20d2 2510 adata = bfd_alloc (abfd, sizeof (mach_o_fat_data_struct));
3af9a47b 2511 if (adata == NULL)
e84d6fca 2512 goto error;
a95a4550 2513
3af9a47b
NC
2514 adata->magic = bfd_getb32 (buf);
2515 adata->nfat_arch = bfd_getb32 (buf + 4);
2516 if (adata->magic != 0xcafebabe)
e84d6fca 2517 goto error;
27cc28f9
AS
2518 /* Avoid matching Java bytecode files, which have the same magic number.
2519 In the Java bytecode file format this field contains the JVM version,
2520 which starts at 43.0. */
2521 if (adata->nfat_arch > 30)
2522 goto error;
3af9a47b 2523
c2f09c75 2524 adata->archentries =
3af9a47b
NC
2525 bfd_alloc (abfd, adata->nfat_arch * sizeof (mach_o_fat_archentry));
2526 if (adata->archentries == NULL)
e84d6fca 2527 goto error;
3af9a47b
NC
2528
2529 for (i = 0; i < adata->nfat_arch; i++)
2530 {
c2f09c75
TG
2531 if (bfd_seek (abfd, 8 + 20 * i, SEEK_SET) != 0
2532 || bfd_bread ((PTR) buf, 20, abfd) != 20)
e84d6fca 2533 goto error;
3af9a47b
NC
2534 adata->archentries[i].cputype = bfd_getb32 (buf);
2535 adata->archentries[i].cpusubtype = bfd_getb32 (buf + 4);
2536 adata->archentries[i].offset = bfd_getb32 (buf + 8);
2537 adata->archentries[i].size = bfd_getb32 (buf + 12);
2538 adata->archentries[i].align = bfd_getb32 (buf + 16);
3af9a47b
NC
2539 }
2540
2541 abfd->tdata.mach_o_fat_data = adata;
2542 return abfd->xvec;
e84d6fca
AM
2543
2544 error:
2545 if (adata != NULL)
2546 bfd_release (abfd, adata);
2547 bfd_set_error (bfd_error_wrong_format);
2548 return NULL;
3af9a47b
NC
2549}
2550
2551bfd *
116c20d2 2552bfd_mach_o_openr_next_archived_file (bfd *archive, bfd *prev)
3af9a47b 2553{
e84d6fca 2554 mach_o_fat_data_struct *adata;
3af9a47b
NC
2555 mach_o_fat_archentry *entry = NULL;
2556 unsigned long i;
15e1c58a 2557 bfd *nbfd;
15e1c58a
TG
2558 enum bfd_architecture arch_type;
2559 unsigned long arch_subtype;
3af9a47b 2560
e84d6fca 2561 adata = (mach_o_fat_data_struct *) archive->tdata.mach_o_fat_data;
3af9a47b
NC
2562 BFD_ASSERT (adata != NULL);
2563
2564 /* Find index of previous entry. */
2565 if (prev == NULL)
2566 i = 0; /* Start at first one. */
2567 else
2568 {
2569 for (i = 0; i < adata->nfat_arch; i++)
2570 {
15e1c58a 2571 if (adata->archentries[i].offset == prev->origin)
3af9a47b
NC
2572 break;
2573 }
2574
2575 if (i == adata->nfat_arch)
2576 {
2577 /* Not found. */
2578 bfd_set_error (bfd_error_bad_value);
a95a4550 2579 return NULL;
3af9a47b
NC
2580 }
2581 i++; /* Get next entry. */
2582 }
a95a4550 2583
3af9a47b
NC
2584 if (i >= adata->nfat_arch)
2585 {
2586 bfd_set_error (bfd_error_no_more_archived_files);
2587 return NULL;
2588 }
2589
2590 entry = &adata->archentries[i];
15e1c58a
TG
2591 nbfd = _bfd_new_bfd_contained_in (archive);
2592 if (nbfd == NULL)
2593 return NULL;
2594
2595 nbfd->origin = entry->offset;
2596
2597 bfd_mach_o_convert_architecture (entry->cputype, entry->cpusubtype,
2598 &arch_type, &arch_subtype);
846b9259
TG
2599 /* Create the member filename.
2600 Use FILENAME:ARCH_NAME. */
2601 {
2602 char *s = NULL;
2603 const char *arch_name;
2604 size_t arch_file_len = strlen (bfd_get_filename (archive));
2605
2606 arch_name = bfd_printable_arch_mach (arch_type, arch_subtype);
2607 s = bfd_malloc (arch_file_len + 1 + strlen (arch_name) + 1);
2608 if (s == NULL)
2609 return NULL;
2610 memcpy (s, bfd_get_filename (archive), arch_file_len);
2611 s[arch_file_len] = ':';
2612 strcpy (s + arch_file_len + 1, arch_name);
2613 nbfd->filename = s;
2614 }
15e1c58a 2615 nbfd->iostream = NULL;
846b9259 2616 bfd_set_arch_mach (nbfd, arch_type, arch_subtype);
3af9a47b 2617
15e1c58a 2618 return nbfd;
3af9a47b
NC
2619}
2620
846b9259
TG
2621/* If ABFD format is FORMAT and architecture is ARCH, return it.
2622 If ABFD is a fat image containing a member that corresponds to FORMAT
2623 and ARCH, returns it.
2624 In other case, returns NULL.
2625 This function allows transparent uses of fat images. */
2626bfd *
2627bfd_mach_o_fat_extract (bfd *abfd,
2628 bfd_format format,
2629 const bfd_arch_info_type *arch)
2630{
2631 bfd *res;
2632 mach_o_fat_data_struct *adata;
2633 unsigned int i;
2634
2635 if (bfd_check_format (abfd, format))
2636 {
2637 if (bfd_get_arch_info (abfd) == arch)
2638 return abfd;
2639 return NULL;
2640 }
2641 if (!bfd_check_format (abfd, bfd_archive)
2642 || abfd->xvec != &mach_o_fat_vec)
2643 return NULL;
c2f09c75 2644
846b9259
TG
2645 /* This is a Mach-O fat image. */
2646 adata = (mach_o_fat_data_struct *) abfd->tdata.mach_o_fat_data;
2647 BFD_ASSERT (adata != NULL);
2648
2649 for (i = 0; i < adata->nfat_arch; i++)
2650 {
2651 struct mach_o_fat_archentry *e = &adata->archentries[i];
2652 enum bfd_architecture cpu_type;
2653 unsigned long cpu_subtype;
2654
2655 bfd_mach_o_convert_architecture (e->cputype, e->cpusubtype,
2656 &cpu_type, &cpu_subtype);
2657 if (cpu_type != arch->arch || cpu_subtype != arch->mach)
2658 continue;
2659
2660 /* The architecture is found. */
2661 res = _bfd_new_bfd_contained_in (abfd);
2662 if (res == NULL)
2663 return NULL;
2664
2665 res->origin = e->offset;
2666
2667 res->filename = strdup (abfd->filename);
2668 res->iostream = NULL;
2669
2670 if (bfd_check_format (res, format))
2671 {
2672 BFD_ASSERT (bfd_get_arch_info (res) == arch);
2673 return res;
2674 }
2675 bfd_close (res);
2676 return NULL;
2677 }
2678
2679 return NULL;
2680}
2681
e84d6fca 2682int
116c20d2
NC
2683bfd_mach_o_lookup_section (bfd *abfd,
2684 asection *section,
2685 bfd_mach_o_load_command **mcommand,
2686 bfd_mach_o_section **msection)
3af9a47b
NC
2687{
2688 struct mach_o_data_struct *md = abfd->tdata.mach_o_data;
2689 unsigned int i, j, num;
2690
2691 bfd_mach_o_load_command *ncmd = NULL;
2692 bfd_mach_o_section *nsect = NULL;
2693
2694 BFD_ASSERT (mcommand != NULL);
2695 BFD_ASSERT (msection != NULL);
2696
2697 num = 0;
2698 for (i = 0; i < md->header.ncmds; i++)
2699 {
2700 struct bfd_mach_o_load_command *cmd = &md->commands[i];
2701 struct bfd_mach_o_segment_command *seg = NULL;
2702
1e8a024a
TG
2703 if (cmd->type != BFD_MACH_O_LC_SEGMENT
2704 || cmd->type != BFD_MACH_O_LC_SEGMENT_64)
3af9a47b
NC
2705 continue;
2706 seg = &cmd->command.segment;
a95a4550 2707
3af9a47b
NC
2708 if (seg->segment == section)
2709 {
2710 if (num == 0)
2711 ncmd = cmd;
2712 num++;
2713 }
2714
2715 for (j = 0; j < seg->nsects; j++)
2716 {
2717 struct bfd_mach_o_section *sect = &seg->sections[j];
2718
2719 if (sect->bfdsection == section)
2720 {
2721 if (num == 0)
2722 nsect = sect;
2723 num++;
2724 }
2725 }
2726 }
a95a4550 2727
3af9a47b
NC
2728 *mcommand = ncmd;
2729 *msection = nsect;
2730 return num;
2731}
2732
2733int
116c20d2
NC
2734bfd_mach_o_lookup_command (bfd *abfd,
2735 bfd_mach_o_load_command_type type,
2736 bfd_mach_o_load_command **mcommand)
3af9a47b
NC
2737{
2738 struct mach_o_data_struct *md = NULL;
2739 bfd_mach_o_load_command *ncmd = NULL;
2740 unsigned int i, num;
2741
2742 md = abfd->tdata.mach_o_data;
2743
2744 BFD_ASSERT (md != NULL);
2745 BFD_ASSERT (mcommand != NULL);
2746
2747 num = 0;
2748 for (i = 0; i < md->header.ncmds; i++)
2749 {
2750 struct bfd_mach_o_load_command *cmd = &md->commands[i];
2751
2752 if (cmd->type != type)
2753 continue;
2754
2755 if (num == 0)
2756 ncmd = cmd;
2757 num++;
2758 }
2759
2760 *mcommand = ncmd;
2761 return num;
2762}
2763
2764unsigned long
116c20d2 2765bfd_mach_o_stack_addr (enum bfd_mach_o_cpu_type type)
3af9a47b
NC
2766{
2767 switch (type)
2768 {
2769 case BFD_MACH_O_CPU_TYPE_MC680x0:
2770 return 0x04000000;
2771 case BFD_MACH_O_CPU_TYPE_MC88000:
2772 return 0xffffe000;
2773 case BFD_MACH_O_CPU_TYPE_POWERPC:
2774 return 0xc0000000;
2775 case BFD_MACH_O_CPU_TYPE_I386:
2776 return 0xc0000000;
2777 case BFD_MACH_O_CPU_TYPE_SPARC:
2778 return 0xf0000000;
2779 case BFD_MACH_O_CPU_TYPE_I860:
2780 return 0;
2781 case BFD_MACH_O_CPU_TYPE_HPPA:
e84d6fca 2782 return 0xc0000000 - 0x04000000;
3af9a47b
NC
2783 default:
2784 return 0;
2785 }
2786}
2787
154a1ee5 2788bfd_boolean
15e1c58a
TG
2789bfd_mach_o_bfd_print_private_bfd_data (bfd *abfd, PTR ptr)
2790{
2791 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
2792 FILE *file = (FILE *) ptr;
2793 unsigned int i, j;
2794 unsigned int sec_nbr = 0;
2795
2796 fprintf (file, _("Segments and Sections:\n"));
2797 fprintf (file, _(" #: Segment name Section name Address\n"));
2798
2799 for (i = 0; i < mdata->header.ncmds; i++)
2800 {
2801 bfd_mach_o_segment_command *seg;
2802
2803 if (mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT
2804 && mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT_64)
2805 continue;
2806
2807 seg = &mdata->commands[i].command.segment;
2808
2809 fprintf (file, "[Segment %-16s ", seg->segname);
2810 fprintf_vma (file, seg->vmaddr);
2811 fprintf (file, "-");
2812 fprintf_vma (file, seg->vmaddr + seg->vmsize - 1);
2813 fputc (' ', file);
2814 fputc (seg->initprot & BFD_MACH_O_PROT_READ ? 'r' : '-', file);
2815 fputc (seg->initprot & BFD_MACH_O_PROT_WRITE ? 'w' : '-', file);
2816 fputc (seg->initprot & BFD_MACH_O_PROT_EXECUTE ? 'x' : '-', file);
2817 fprintf (file, "]\n");
2818 for (j = 0; j < seg->nsects; j++)
2819 {
2820 bfd_mach_o_section *sec = &seg->sections[j];
2821 fprintf (file, "%02u: %-16s %-16s ", ++sec_nbr,
2822 sec->segname, sec->sectname);
2823 fprintf_vma (file, sec->addr);
2824 fprintf (file, " ");
2825 fprintf_vma (file, sec->size);
2826 fprintf (file, " %08lx\n", sec->flags);
2827 }
2828 }
2829
2830 for (i = 0; i < mdata->header.ncmds; i++)
2831 {
2832 bfd_mach_o_load_command *cmd = &mdata->commands[i];
2833
2834 switch (cmd->type)
2835 {
2836 case BFD_MACH_O_LC_SEGMENT:
2837 case BFD_MACH_O_LC_SEGMENT_64:
2838 break;
2839 case BFD_MACH_O_LC_UUID:
2840 {
2841 bfd_mach_o_uuid_command *uuid = &cmd->command.uuid;
2842 unsigned int i;
2843
2844 fprintf (file, "\n"
2845 "UUID:");
2846 for (i = 0; i < sizeof (uuid->uuid); i++)
2847 fprintf (file, " %02x", uuid->uuid[i]);
2848 fputc ('\n', file);
2849 }
2850 break;
2851 case BFD_MACH_O_LC_LOAD_DYLIB:
2852 {
2853 bfd_mach_o_dylib_command *dylib = &cmd->command.dylib;
2854 bfd_byte *data = NULL;
2855
2856 if (! bfd_malloc_and_get_section (abfd, dylib->section, &data))
2857 {
2858 if (data != NULL)
2859 free (data);
2860 break;
2861 }
2862 fprintf (file, "\n"
2863 "LOAD_DYLIB: %s\n",
2864 data + dylib->name_offset - cmd->offset - 8);
2865 fprintf (file, " time stamp: 0x%08lx\n",
2866 dylib->timestamp);
2867 fprintf (file, " current version: 0x%08lx\n",
2868 dylib->current_version);
2869 fprintf (file, " comptibility version: 0x%08lx\n",
2870 dylib->compatibility_version);
2871 free (data);
2872 break;
2873 }
2874 case BFD_MACH_O_LC_LOAD_DYLINKER:
2875 {
2876 bfd_mach_o_dylinker_command *linker = &cmd->command.dylinker;
2877 bfd_byte *data = NULL;
2878
2879 if (! bfd_malloc_and_get_section (abfd, linker->section, &data))
2880 {
2881 if (data != NULL)
2882 free (data);
2883 break;
2884 }
2885 fprintf (file, "\n"
2886 "LOAD_DYLINKER: %s\n",
2887 data + linker->name_offset - cmd->offset - 8);
2888 free (data);
2889 break;
2890 }
2891 case BFD_MACH_O_LC_SYMTAB:
2892 {
2893 bfd_mach_o_symtab_command *symtab = &cmd->command.symtab;
2894 fprintf (file, "\n"
92bc0e80 2895 "LC_SYMTAB: nsyms: %u, strsize: %u\n",
15e1c58a
TG
2896 symtab->nsyms, symtab->strsize);
2897 break;
2898 }
2899 case BFD_MACH_O_LC_DYSYMTAB:
2900 {
2901 bfd_mach_o_dysymtab_command *dysymtab = &cmd->command.dysymtab;
2902 fprintf (file, "\n"
2903 "LC_DYSYMTAB:\n"
2904 " local symbols: index: %lu number: %lu\n",
2905 dysymtab->ilocalsym, dysymtab->nlocalsym);
2906 fprintf (file,
2907 " external symbols: index: %lu number: %lu\n",
2908 dysymtab->iextdefsym, dysymtab->nextdefsym);
2909 fprintf (file,
2910 " undefined symbols: index: %lu number: %lu\n",
2911 dysymtab->iundefsym, dysymtab->nundefsym);
2912 fprintf (file,
2913 " ntoc: offset: %lu number: %lu\n",
2914 dysymtab->tocoff, dysymtab->ntoc);
2915 fprintf (file,
2916 " module table: offset: %lu number: %lu\n",
2917 dysymtab->modtaboff, dysymtab->nmodtab);
2918 break;
2919 }
2920 default:
2921 fprintf (file, "LC_%d\n", cmd->type);
2922 break;
2923 }
2924 }
2925
2926 return TRUE;
2927}
2928
3af9a47b 2929int
116c20d2
NC
2930bfd_mach_o_core_fetch_environment (bfd *abfd,
2931 unsigned char **rbuf,
2932 unsigned int *rlen)
3af9a47b
NC
2933{
2934 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
2935 unsigned long stackaddr = bfd_mach_o_stack_addr (mdata->header.cputype);
2936 unsigned int i = 0;
2937
2938 for (i = 0; i < mdata->header.ncmds; i++)
2939 {
2940 bfd_mach_o_load_command *cur = &mdata->commands[i];
2941 bfd_mach_o_segment_command *seg = NULL;
2942
2943 if (cur->type != BFD_MACH_O_LC_SEGMENT)
2944 continue;
2945
2946 seg = &cur->command.segment;
2947
2948 if ((seg->vmaddr + seg->vmsize) == stackaddr)
2949 {
2950 unsigned long start = seg->fileoff;
2951 unsigned long end = seg->fileoff + seg->filesize;
2952 unsigned char *buf = bfd_malloc (1024);
2953 unsigned long size = 1024;
2954
2955 for (;;)
2956 {
2957 bfd_size_type nread = 0;
2958 unsigned long offset;
2959 int found_nonnull = 0;
2960
2961 if (size > (end - start))
2962 size = (end - start);
2963
515ef31d
NC
2964 buf = bfd_realloc_or_free (buf, size);
2965 if (buf == NULL)
2966 return -1;
c2f09c75
TG
2967
2968 if (bfd_seek (abfd, end - size, SEEK_SET) != 0)
2969 {
2970 free (buf);
2971 return -1;
2972 }
2973
3af9a47b 2974 nread = bfd_bread (buf, size, abfd);
a95a4550 2975
3af9a47b 2976 if (nread != size)
515ef31d
NC
2977 {
2978 free (buf);
2979 return -1;
2980 }
a95a4550 2981
3af9a47b
NC
2982 for (offset = 4; offset <= size; offset += 4)
2983 {
e84d6fca 2984 unsigned long val;
3af9a47b 2985
e84d6fca 2986 val = *((unsigned long *) (buf + size - offset));
3af9a47b
NC
2987 if (! found_nonnull)
2988 {
2989 if (val != 0)
2990 found_nonnull = 1;
2991 }
2992 else if (val == 0x0)
2993 {
e84d6fca
AM
2994 unsigned long bottom;
2995 unsigned long top;
3af9a47b 2996
e84d6fca
AM
2997 bottom = seg->fileoff + seg->filesize - offset;
2998 top = seg->fileoff + seg->filesize - 4;
3af9a47b
NC
2999 *rbuf = bfd_malloc (top - bottom);
3000 *rlen = top - bottom;
3001
3002 memcpy (*rbuf, buf + size - *rlen, *rlen);
515ef31d 3003 free (buf);
3af9a47b
NC
3004 return 0;
3005 }
3006 }
3007
3008 if (size == (end - start))
3009 break;
3010
3011 size *= 2;
3012 }
515ef31d
NC
3013
3014 free (buf);
3af9a47b
NC
3015 }
3016 }
3017
3018 return -1;
3019}
3020
3021char *
116c20d2 3022bfd_mach_o_core_file_failing_command (bfd *abfd)
3af9a47b
NC
3023{
3024 unsigned char *buf = NULL;
3025 unsigned int len = 0;
3026 int ret = -1;
3027
3028 ret = bfd_mach_o_core_fetch_environment (abfd, &buf, &len);
3029 if (ret < 0)
3030 return NULL;
3031
f075ee0c 3032 return (char *) buf;
3af9a47b
NC
3033}
3034
3035int
116c20d2 3036bfd_mach_o_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
3af9a47b
NC
3037{
3038 return 0;
3039}
3040
92bc0e80
TG
3041#define bfd_mach_o_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
3042#define bfd_mach_o_bfd_reloc_name_lookup _bfd_norelocs_bfd_reloc_name_lookup
3043
3044#define bfd_mach_o_swap_reloc_in NULL
3045#define bfd_mach_o_swap_reloc_out NULL
3046
116c20d2
NC
3047#define TARGET_NAME mach_o_be_vec
3048#define TARGET_STRING "mach-o-be"
3049#define TARGET_BIG_ENDIAN 1
3050#define TARGET_ARCHIVE 0
3af9a47b
NC
3051#include "mach-o-target.c"
3052
3053#undef TARGET_NAME
3054#undef TARGET_STRING
3055#undef TARGET_BIG_ENDIAN
3056#undef TARGET_ARCHIVE
3057
116c20d2
NC
3058#define TARGET_NAME mach_o_le_vec
3059#define TARGET_STRING "mach-o-le"
3060#define TARGET_BIG_ENDIAN 0
3061#define TARGET_ARCHIVE 0
3af9a47b
NC
3062
3063#include "mach-o-target.c"
3064
3065#undef TARGET_NAME
3066#undef TARGET_STRING
3067#undef TARGET_BIG_ENDIAN
3068#undef TARGET_ARCHIVE
3069
116c20d2
NC
3070#define TARGET_NAME mach_o_fat_vec
3071#define TARGET_STRING "mach-o-fat"
3072#define TARGET_BIG_ENDIAN 1
3073#define TARGET_ARCHIVE 1
3af9a47b
NC
3074
3075#include "mach-o-target.c"
3076
3077#undef TARGET_NAME
3078#undef TARGET_STRING
3079#undef TARGET_BIG_ENDIAN
3080#undef TARGET_ARCHIVE
This page took 0.517946 seconds and 4 git commands to generate.