2007-07-03 Markus Deuling <deuling@de.ibm.com>
[deliverable/binutils-gdb.git] / bfd / mach-o.c
CommitLineData
3af9a47b 1/* Mach-O support for BFD.
72f6ea61 2 Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
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
9 the Free Software Foundation; either version 2 of the License, or
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
3e110533 19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
3af9a47b 20
3db64b00 21#include "sysdep.h"
3af9a47b
NC
22#include "mach-o.h"
23#include "bfd.h"
3af9a47b
NC
24#include "libbfd.h"
25#include "libiberty.h"
26#include <ctype.h>
27
28#ifndef BFD_IO_FUNCS
29#define BFD_IO_FUNCS 0
30#endif
31
116c20d2
NC
32#define bfd_mach_o_mkarchive _bfd_noarchive_mkarchive
33#define bfd_mach_o_read_ar_hdr _bfd_noarchive_read_ar_hdr
34#define bfd_mach_o_slurp_armap _bfd_noarchive_slurp_armap
35#define bfd_mach_o_slurp_extended_name_table _bfd_noarchive_slurp_extended_name_table
36#define bfd_mach_o_construct_extended_name_table _bfd_noarchive_construct_extended_name_table
37#define bfd_mach_o_truncate_arname _bfd_noarchive_truncate_arname
38#define bfd_mach_o_write_armap _bfd_noarchive_write_armap
39#define bfd_mach_o_get_elt_at_index _bfd_noarchive_get_elt_at_index
40#define bfd_mach_o_generic_stat_arch_elt _bfd_noarchive_generic_stat_arch_elt
41#define bfd_mach_o_update_armap_timestamp _bfd_noarchive_update_armap_timestamp
42#define bfd_mach_o_close_and_cleanup _bfd_generic_close_and_cleanup
43#define bfd_mach_o_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
44#define bfd_mach_o_new_section_hook _bfd_generic_new_section_hook
45#define bfd_mach_o_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
46#define bfd_mach_o_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name
47#define bfd_mach_o_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
48#define bfd_mach_o_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name
49#define bfd_mach_o_get_lineno _bfd_nosymbols_get_lineno
50#define bfd_mach_o_find_nearest_line _bfd_nosymbols_find_nearest_line
4ab527b0 51#define bfd_mach_o_find_inliner_info _bfd_nosymbols_find_inliner_info
116c20d2
NC
52#define bfd_mach_o_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
53#define bfd_mach_o_read_minisymbols _bfd_generic_read_minisymbols
54#define bfd_mach_o_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
3af9a47b 55#define bfd_mach_o_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
116c20d2
NC
56#define bfd_mach_o_bfd_relax_section bfd_generic_relax_section
57#define bfd_mach_o_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
58#define bfd_mach_o_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
59#define bfd_mach_o_bfd_link_add_symbols _bfd_generic_link_add_symbols
60#define bfd_mach_o_bfd_link_just_syms _bfd_generic_link_just_syms
61#define bfd_mach_o_bfd_final_link _bfd_generic_final_link
62#define bfd_mach_o_bfd_link_split_section _bfd_generic_link_split_section
63#define bfd_mach_o_set_arch_mach bfd_default_set_arch_mach
64#define bfd_mach_o_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
65#define bfd_mach_o_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
66#define bfd_mach_o_bfd_print_private_bfd_data _bfd_generic_bfd_print_private_bfd_data
67#define bfd_mach_o_get_section_contents _bfd_generic_get_section_contents
68#define bfd_mach_o_set_section_contents _bfd_generic_set_section_contents
69#define bfd_mach_o_bfd_gc_sections bfd_generic_gc_sections
70#define bfd_mach_o_bfd_merge_sections bfd_generic_merge_sections
71#define bfd_mach_o_bfd_is_group_section bfd_generic_is_group_section
72#define bfd_mach_o_bfd_discard_group bfd_generic_discard_group
73#define bfd_mach_o_section_already_linked _bfd_generic_section_already_linked
74#define bfd_mach_o_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data
69d246d9 75#define bfd_mach_o_core_file_matches_executable_p generic_core_file_matches_executable_p
116c20d2 76
3af9a47b
NC
77
78/* The flags field of a section structure is separated into two parts a section
79 type and section attributes. The section types are mutually exclusive (it
80 can only have one type) but the section attributes are not (it may have more
81 than one attribute). */
82
83#define SECTION_TYPE 0x000000ff /* 256 section types. */
84#define SECTION_ATTRIBUTES 0xffffff00 /* 24 section attributes. */
85
86/* Constants for the section attributes part of the flags field of a section
87 structure. */
88
89#define SECTION_ATTRIBUTES_USR 0xff000000 /* User-settable attributes. */
90#define S_ATTR_PURE_INSTRUCTIONS 0x80000000 /* Section contains only true machine instructions. */
91#define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* System setable attributes. */
92#define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* Section contains some machine instructions. */
93#define S_ATTR_EXT_RELOC 0x00000200 /* Section has external relocation entries. */
94#define S_ATTR_LOC_RELOC 0x00000100 /* Section has local relocation entries. */
95
96#define N_STAB 0xe0
97#define N_TYPE 0x1e
98#define N_EXT 0x01
99#define N_UNDF 0x0
100#define N_ABS 0x2
101#define N_SECT 0xe
102#define N_INDR 0xa
103
b34976b6 104bfd_boolean
116c20d2 105bfd_mach_o_valid (bfd *abfd)
3af9a47b
NC
106{
107 if (abfd == NULL || abfd->xvec == NULL)
108 return 0;
109
110 if (! ((abfd->xvec == &mach_o_be_vec)
111 || (abfd->xvec == &mach_o_le_vec)
112 || (abfd->xvec == &mach_o_fat_vec)))
113 return 0;
114
115 if (abfd->tdata.mach_o_data == NULL)
116 return 0;
117 return 1;
118}
119
120/* Copy any private info we understand from the input symbol
121 to the output symbol. */
122
b34976b6 123static bfd_boolean
116c20d2
NC
124bfd_mach_o_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
125 asymbol *isymbol ATTRIBUTE_UNUSED,
126 bfd *obfd ATTRIBUTE_UNUSED,
127 asymbol *osymbol ATTRIBUTE_UNUSED)
3af9a47b 128{
b34976b6 129 return TRUE;
3af9a47b
NC
130}
131
132/* Copy any private info we understand from the input section
133 to the output section. */
134
b34976b6 135static bfd_boolean
116c20d2
NC
136bfd_mach_o_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
137 asection *isection ATTRIBUTE_UNUSED,
138 bfd *obfd ATTRIBUTE_UNUSED,
139 asection *osection ATTRIBUTE_UNUSED)
3af9a47b 140{
b34976b6 141 return TRUE;
3af9a47b
NC
142}
143
144/* Copy any private info we understand from the input bfd
145 to the output bfd. */
146
b34976b6 147static bfd_boolean
116c20d2 148bfd_mach_o_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
3af9a47b
NC
149{
150 BFD_ASSERT (bfd_mach_o_valid (ibfd));
151 BFD_ASSERT (bfd_mach_o_valid (obfd));
152
153 obfd->tdata.mach_o_data = ibfd->tdata.mach_o_data;
154 obfd->tdata.mach_o_data->ibfd = ibfd;
b34976b6 155 return TRUE;
3af9a47b
NC
156}
157
158static long
116c20d2 159bfd_mach_o_count_symbols (bfd *abfd)
3af9a47b
NC
160{
161 bfd_mach_o_data_struct *mdata = NULL;
162 long nsyms = 0;
163 unsigned long i;
a95a4550 164
3af9a47b
NC
165 BFD_ASSERT (bfd_mach_o_valid (abfd));
166 mdata = abfd->tdata.mach_o_data;
167
168 for (i = 0; i < mdata->header.ncmds; i++)
169 if (mdata->commands[i].type == BFD_MACH_O_LC_SYMTAB)
170 {
171 bfd_mach_o_symtab_command *sym = &mdata->commands[i].command.symtab;
172 nsyms += sym->nsyms;
173 }
174
175 return nsyms;
176}
177
178static long
116c20d2 179bfd_mach_o_get_symtab_upper_bound (bfd *abfd)
3af9a47b
NC
180{
181 long nsyms = bfd_mach_o_count_symbols (abfd);
182
183 if (nsyms < 0)
184 return nsyms;
185
186 return ((nsyms + 1) * sizeof (asymbol *));
187}
188
189static long
116c20d2 190bfd_mach_o_canonicalize_symtab (bfd *abfd, asymbol **alocation)
3af9a47b
NC
191{
192 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
193 long nsyms = bfd_mach_o_count_symbols (abfd);
194 asymbol **csym = alocation;
195 unsigned long i, j;
196
197 if (nsyms < 0)
198 return nsyms;
199
200 for (i = 0; i < mdata->header.ncmds; i++)
201 {
202 if (mdata->commands[i].type == BFD_MACH_O_LC_SYMTAB)
203 {
204 bfd_mach_o_symtab_command *sym = &mdata->commands[i].command.symtab;
205
206 if (bfd_mach_o_scan_read_symtab_symbols (abfd, &mdata->commands[i].command.symtab) != 0)
207 {
6cee3f79 208 fprintf (stderr, "bfd_mach_o_canonicalize_symtab: unable to load symbols for section %lu\n", i);
3af9a47b
NC
209 return 0;
210 }
211
212 BFD_ASSERT (sym->symbols != NULL);
213
214 for (j = 0; j < sym->nsyms; j++)
215 {
216 BFD_ASSERT (csym < (alocation + nsyms));
217 *csym++ = &sym->symbols[j];
218 }
219 }
220 }
221
222 *csym++ = NULL;
a95a4550 223
3af9a47b
NC
224 return nsyms;
225}
226
227static void
116c20d2
NC
228bfd_mach_o_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
229 asymbol *symbol,
230 symbol_info *ret)
3af9a47b
NC
231{
232 bfd_symbol_info (symbol, ret);
233}
234
235static void
116c20d2
NC
236bfd_mach_o_print_symbol (bfd *abfd,
237 PTR afile,
238 asymbol *symbol,
239 bfd_print_symbol_type how)
3af9a47b
NC
240{
241 FILE *file = (FILE *) afile;
242
243 switch (how)
244 {
245 case bfd_print_symbol_name:
246 fprintf (file, "%s", symbol->name);
247 break;
248 default:
249 bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
250 fprintf (file, " %-5s %s", symbol->section->name, symbol->name);
251 }
252}
253
254static void
116c20d2
NC
255bfd_mach_o_convert_architecture (bfd_mach_o_cpu_type mtype,
256 bfd_mach_o_cpu_subtype msubtype ATTRIBUTE_UNUSED,
257 enum bfd_architecture *type,
258 unsigned long *subtype)
3af9a47b
NC
259{
260 *subtype = bfd_arch_unknown;
261
262 switch (mtype)
263 {
264 case BFD_MACH_O_CPU_TYPE_VAX: *type = bfd_arch_vax; break;
265 case BFD_MACH_O_CPU_TYPE_MC680x0: *type = bfd_arch_m68k; break;
266 case BFD_MACH_O_CPU_TYPE_I386: *type = bfd_arch_i386; break;
267 case BFD_MACH_O_CPU_TYPE_MIPS: *type = bfd_arch_mips; break;
268 case BFD_MACH_O_CPU_TYPE_MC98000: *type = bfd_arch_m98k; break;
269 case BFD_MACH_O_CPU_TYPE_HPPA: *type = bfd_arch_hppa; break;
270 case BFD_MACH_O_CPU_TYPE_ARM: *type = bfd_arch_arm; break;
271 case BFD_MACH_O_CPU_TYPE_MC88000: *type = bfd_arch_m88k; break;
272 case BFD_MACH_O_CPU_TYPE_SPARC: *type = bfd_arch_sparc; break;
273 case BFD_MACH_O_CPU_TYPE_I860: *type = bfd_arch_i860; break;
274 case BFD_MACH_O_CPU_TYPE_ALPHA: *type = bfd_arch_alpha; break;
275 case BFD_MACH_O_CPU_TYPE_POWERPC: *type = bfd_arch_powerpc; break;
276 default: *type = bfd_arch_unknown; break;
277 }
278
279 switch (*type)
280 {
281 case bfd_arch_i386: *subtype = bfd_mach_i386_i386; break;
282 case bfd_arch_sparc: *subtype = bfd_mach_sparc; break;
283 default:
284 *subtype = bfd_arch_unknown;
285 }
286}
a95a4550 287
116c20d2
NC
288static int
289bfd_mach_o_write_header (bfd *abfd, bfd_mach_o_header *header)
290{
291 unsigned char buf[28];
292
293 bfd_h_put_32 (abfd, header->magic, buf + 0);
294 bfd_h_put_32 (abfd, header->cputype, buf + 4);
295 bfd_h_put_32 (abfd, header->cpusubtype, buf + 8);
296 bfd_h_put_32 (abfd, header->filetype, buf + 12);
297 bfd_h_put_32 (abfd, header->ncmds, buf + 16);
298 bfd_h_put_32 (abfd, header->sizeofcmds, buf + 20);
299 bfd_h_put_32 (abfd, header->flags, buf + 24);
300
301 bfd_seek (abfd, 0, SEEK_SET);
302 if (bfd_bwrite ((PTR) buf, 28, abfd) != 28)
303 return -1;
304
305 return 0;
306}
307
308static int
309bfd_mach_o_scan_write_thread (bfd *abfd,
310 bfd_mach_o_load_command *command)
311{
312 bfd_mach_o_thread_command *cmd = &command->command.thread;
313 unsigned int i;
314 unsigned char buf[8];
315 bfd_vma offset;
316 unsigned int nflavours;
317
318 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
319 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
320
321 offset = 8;
322 nflavours = 0;
323 for (i = 0; i < cmd->nflavours; i++)
324 {
325 BFD_ASSERT ((cmd->flavours[i].size % 4) == 0);
326 BFD_ASSERT (cmd->flavours[i].offset == (command->offset + offset + 8));
327
328 bfd_h_put_32 (abfd, cmd->flavours[i].flavour, buf);
329 bfd_h_put_32 (abfd, (cmd->flavours[i].size / 4), buf + 4);
330
331 bfd_seek (abfd, command->offset + offset, SEEK_SET);
332 if (bfd_bwrite ((PTR) buf, 8, abfd) != 8)
333 return -1;
334
335 offset += cmd->flavours[i].size + 8;
336 }
337
338 return 0;
339}
340
341static int
342bfd_mach_o_scan_write_section (bfd *abfd,
343 bfd_mach_o_section *section,
344 bfd_vma offset)
345{
346 unsigned char buf[68];
347
348 memcpy (buf, section->sectname, 16);
349 memcpy (buf + 16, section->segname, 16);
350 bfd_h_put_32 (abfd, section->addr, buf + 32);
351 bfd_h_put_32 (abfd, section->size, buf + 36);
352 bfd_h_put_32 (abfd, section->offset, buf + 40);
353 bfd_h_put_32 (abfd, section->align, buf + 44);
354 bfd_h_put_32 (abfd, section->reloff, buf + 48);
355 bfd_h_put_32 (abfd, section->nreloc, buf + 52);
356 bfd_h_put_32 (abfd, section->flags, buf + 56);
357 /* bfd_h_put_32 (abfd, section->reserved1, buf + 60); */
358 /* bfd_h_put_32 (abfd, section->reserved2, buf + 64); */
359
360 bfd_seek (abfd, offset, SEEK_SET);
361 if (bfd_bwrite ((PTR) buf, 68, abfd) != 68)
362 return -1;
363
364 return 0;
365}
366
367static int
368bfd_mach_o_scan_write_segment (bfd *abfd, bfd_mach_o_load_command *command)
369{
370 unsigned char buf[48];
371 bfd_mach_o_segment_command *seg = &command->command.segment;
372 unsigned long i;
373
374 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
375
376 memcpy (buf, seg->segname, 16);
377 bfd_h_put_32 (abfd, seg->vmaddr, buf + 16);
378 bfd_h_put_32 (abfd, seg->vmsize, buf + 20);
379 bfd_h_put_32 (abfd, seg->fileoff, buf + 24);
380 bfd_h_put_32 (abfd, seg->filesize, buf + 28);
381 bfd_h_put_32 (abfd, 0 /* seg->maxprot */, buf + 32);
382 bfd_h_put_32 (abfd, 0 /* seg->initprot */, buf + 36);
383 bfd_h_put_32 (abfd, seg->nsects, buf + 40);
384 bfd_h_put_32 (abfd, seg->flags, buf + 44);
385
386 bfd_seek (abfd, command->offset + 8, SEEK_SET);
387 if (bfd_bwrite ((PTR) buf, 48, abfd) != 48)
388 return -1;
389
390 {
391 char buf[1024];
392 bfd_vma nbytes = seg->filesize;
393 bfd_vma curoff = seg->fileoff;
394
395 while (nbytes > 0)
396 {
397 bfd_vma thisread = nbytes;
398
399 if (thisread > 1024)
400 thisread = 1024;
401
402 bfd_seek (abfd, curoff, SEEK_SET);
403 if (bfd_bread ((PTR) buf, thisread, abfd) != thisread)
404 return -1;
405
406 bfd_seek (abfd, curoff, SEEK_SET);
407 if (bfd_bwrite ((PTR) buf, thisread, abfd) != thisread)
408 return -1;
409
410 nbytes -= thisread;
411 curoff += thisread;
412 }
413 }
414
415 for (i = 0; i < seg->nsects; i++)
416 {
417 bfd_vma segoff = command->offset + 48 + 8 + (i * 68);
418
419 if (bfd_mach_o_scan_write_section (abfd, &seg->sections[i], segoff) != 0)
420 return -1;
421 }
422
423 return 0;
424}
425
426static int
427bfd_mach_o_scan_write_symtab_symbols (bfd *abfd,
428 bfd_mach_o_load_command *command)
429{
430 bfd_mach_o_symtab_command *sym = &command->command.symtab;
431 asymbol *s = NULL;
432 unsigned long i;
433
434 for (i = 0; i < sym->nsyms; i++)
435 {
436 unsigned char buf[12];
437 bfd_vma symoff = sym->symoff + (i * 12);
438 unsigned char ntype = 0;
439 unsigned char nsect = 0;
440 short ndesc = 0;
441
442 s = &sym->symbols[i];
443
444 /* Instead just set from the stored values. */
445 ntype = (s->udata.i >> 24) & 0xff;
446 nsect = (s->udata.i >> 16) & 0xff;
447 ndesc = s->udata.i & 0xffff;
448
449 bfd_h_put_32 (abfd, s->name - sym->strtab, buf);
450 bfd_h_put_8 (abfd, ntype, buf + 4);
451 bfd_h_put_8 (abfd, nsect, buf + 5);
452 bfd_h_put_16 (abfd, ndesc, buf + 6);
453 bfd_h_put_32 (abfd, s->section->vma + s->value, buf + 8);
454
455 bfd_seek (abfd, symoff, SEEK_SET);
456 if (bfd_bwrite ((PTR) buf, 12, abfd) != 12)
457 {
458 fprintf (stderr, "bfd_mach_o_scan_write_symtab_symbols: unable to write %d bytes at %lu\n",
459 12, (unsigned long) symoff);
460 return -1;
461 }
462 }
463
464 return 0;
465}
466
467static int
468bfd_mach_o_scan_write_symtab (bfd *abfd, bfd_mach_o_load_command *command)
469{
470 bfd_mach_o_symtab_command *seg = &command->command.symtab;
471 unsigned char buf[16];
472
473 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
474
475 bfd_h_put_32 (abfd, seg->symoff, buf);
476 bfd_h_put_32 (abfd, seg->nsyms, buf + 4);
477 bfd_h_put_32 (abfd, seg->stroff, buf + 8);
478 bfd_h_put_32 (abfd, seg->strsize, buf + 12);
479
480 bfd_seek (abfd, command->offset + 8, SEEK_SET);
481 if (bfd_bwrite ((PTR) buf, 16, abfd) != 16)
482 return -1;
483
484 if (bfd_mach_o_scan_write_symtab_symbols (abfd, command) != 0)
485 return -1;
486
487 return 0;
488}
489
b34976b6 490static bfd_boolean
116c20d2 491bfd_mach_o_write_contents (bfd *abfd)
3af9a47b
NC
492{
493 unsigned int i;
494 asection *s;
495
496 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
497
498 /* Write data sections first in case they overlap header data to be
499 written later. */
500
501 for (s = abfd->sections; s != (asection *) NULL; s = s->next)
502 ;
503
3af9a47b
NC
504 /* Now write header information. */
505 if (bfd_mach_o_write_header (abfd, &mdata->header) != 0)
b34976b6 506 return FALSE;
3af9a47b
NC
507
508 for (i = 0; i < mdata->header.ncmds; i++)
509 {
510 unsigned char buf[8];
511 bfd_mach_o_load_command *cur = &mdata->commands[i];
512 unsigned long typeflag;
513
514 typeflag = cur->type_required ? cur->type & BFD_MACH_O_LC_REQ_DYLD : cur->type;
515
516 bfd_h_put_32 (abfd, typeflag, buf);
517 bfd_h_put_32 (abfd, cur->len, buf + 4);
518
519 bfd_seek (abfd, cur->offset, SEEK_SET);
520 if (bfd_bwrite ((PTR) buf, 8, abfd) != 8)
b34976b6 521 return FALSE;
3af9a47b
NC
522
523 switch (cur->type)
524 {
525 case BFD_MACH_O_LC_SEGMENT:
526 if (bfd_mach_o_scan_write_segment (abfd, cur) != 0)
b34976b6 527 return FALSE;
3af9a47b
NC
528 break;
529 case BFD_MACH_O_LC_SYMTAB:
530 if (bfd_mach_o_scan_write_symtab (abfd, cur) != 0)
b34976b6 531 return FALSE;
3af9a47b
NC
532 break;
533 case BFD_MACH_O_LC_SYMSEG:
534 break;
535 case BFD_MACH_O_LC_THREAD:
536 case BFD_MACH_O_LC_UNIXTHREAD:
537 if (bfd_mach_o_scan_write_thread (abfd, cur) != 0)
b34976b6 538 return FALSE;
3af9a47b
NC
539 break;
540 case BFD_MACH_O_LC_LOADFVMLIB:
541 case BFD_MACH_O_LC_IDFVMLIB:
542 case BFD_MACH_O_LC_IDENT:
543 case BFD_MACH_O_LC_FVMFILE:
544 case BFD_MACH_O_LC_PREPAGE:
545 case BFD_MACH_O_LC_DYSYMTAB:
546 case BFD_MACH_O_LC_LOAD_DYLIB:
547 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
548 case BFD_MACH_O_LC_ID_DYLIB:
549 case BFD_MACH_O_LC_LOAD_DYLINKER:
550 case BFD_MACH_O_LC_ID_DYLINKER:
551 case BFD_MACH_O_LC_PREBOUND_DYLIB:
552 case BFD_MACH_O_LC_ROUTINES:
553 case BFD_MACH_O_LC_SUB_FRAMEWORK:
554 break;
555 default:
556 fprintf (stderr,
557 "unable to write unknown load command 0x%lx\n",
558 (long) cur->type);
b34976b6 559 return FALSE;
3af9a47b
NC
560 }
561 }
562
b34976b6 563 return TRUE;
3af9a47b
NC
564}
565
566static int
116c20d2 567bfd_mach_o_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
a6b96beb 568 struct bfd_link_info *info ATTRIBUTE_UNUSED)
3af9a47b
NC
569{
570 return 0;
571}
572
573/* Make an empty symbol. This is required only because
574 bfd_make_section_anyway wants to create a symbol for the section. */
575
576static asymbol *
116c20d2 577bfd_mach_o_make_empty_symbol (bfd *abfd)
3af9a47b
NC
578{
579 asymbol *new;
580
116c20d2 581 new = bfd_zalloc (abfd, sizeof (* new));
3af9a47b
NC
582 if (new == NULL)
583 return new;
584 new->the_bfd = abfd;
585 return new;
586}
587
588static int
116c20d2 589bfd_mach_o_read_header (bfd *abfd, bfd_mach_o_header *header)
3af9a47b
NC
590{
591 unsigned char buf[28];
edeb6e24 592 bfd_vma (*get32) (const void *) = NULL;
3af9a47b
NC
593
594 bfd_seek (abfd, 0, SEEK_SET);
595
596 if (bfd_bread ((PTR) buf, 28, abfd) != 28)
597 return -1;
598
599 if (bfd_getb32 (buf) == 0xfeedface)
600 {
601 header->byteorder = BFD_ENDIAN_BIG;
602 header->magic = 0xfeedface;
603 get32 = bfd_getb32;
604 }
605 else if (bfd_getl32 (buf) == 0xfeedface)
606 {
a95a4550 607 header->byteorder = BFD_ENDIAN_LITTLE;
3af9a47b
NC
608 header->magic = 0xfeedface;
609 get32 = bfd_getl32;
610 }
611 else
612 {
613 header->byteorder = BFD_ENDIAN_UNKNOWN;
614 return -1;
615 }
a95a4550 616
3af9a47b
NC
617 header->cputype = (*get32) (buf + 4);
618 header->cpusubtype = (*get32) (buf + 8);
619 header->filetype = (*get32) (buf + 12);
620 header->ncmds = (*get32) (buf + 16);
621 header->sizeofcmds = (*get32) (buf + 20);
622 header->flags = (*get32) (buf + 24);
623
624 return 0;
625}
626
627static asection *
116c20d2 628bfd_mach_o_make_bfd_section (bfd *abfd, bfd_mach_o_section *section)
3af9a47b
NC
629{
630 asection *bfdsec;
631 char *sname;
632 const char *prefix = "LC_SEGMENT";
633 unsigned int snamelen;
117ed4f8 634 flagword flags;
3af9a47b
NC
635
636 snamelen = strlen (prefix) + 1
637 + strlen (section->segname) + 1
638 + strlen (section->sectname) + 1;
639
116c20d2 640 sname = bfd_alloc (abfd, snamelen);
3af9a47b
NC
641 if (sname == NULL)
642 return NULL;
643 sprintf (sname, "%s.%s.%s", prefix, section->segname, section->sectname);
644
117ed4f8
AM
645 flags = SEC_ALLOC;
646 if (!(section->flags & BFD_MACH_O_S_ZEROFILL))
647 flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE;
648 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, flags);
3af9a47b
NC
649 if (bfdsec == NULL)
650 return NULL;
a95a4550 651
3af9a47b
NC
652 bfdsec->vma = section->addr;
653 bfdsec->lma = section->addr;
eea6121a 654 bfdsec->size = section->size;
3af9a47b
NC
655 bfdsec->filepos = section->offset;
656 bfdsec->alignment_power = section->align;
657
3af9a47b
NC
658 return bfdsec;
659}
660
661static int
116c20d2
NC
662bfd_mach_o_scan_read_section (bfd *abfd,
663 bfd_mach_o_section *section,
664 bfd_vma offset)
3af9a47b
NC
665{
666 unsigned char buf[68];
667
668 bfd_seek (abfd, offset, SEEK_SET);
669 if (bfd_bread ((PTR) buf, 68, abfd) != 68)
670 return -1;
a95a4550 671
3af9a47b
NC
672 memcpy (section->sectname, buf, 16);
673 section->sectname[16] = '\0';
674 memcpy (section->segname, buf + 16, 16);
675 section->segname[16] = '\0';
676 section->addr = bfd_h_get_32 (abfd, buf + 32);
677 section->size = bfd_h_get_32 (abfd, buf + 36);
678 section->offset = bfd_h_get_32 (abfd, buf + 40);
679 section->align = bfd_h_get_32 (abfd, buf + 44);
680 section->reloff = bfd_h_get_32 (abfd, buf + 48);
681 section->nreloc = bfd_h_get_32 (abfd, buf + 52);
682 section->flags = bfd_h_get_32 (abfd, buf + 56);
683 section->reserved1 = bfd_h_get_32 (abfd, buf + 60);
684 section->reserved2 = bfd_h_get_32 (abfd, buf + 64);
685 section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section);
686
687 if (section->bfdsection == NULL)
688 return -1;
689
690 return 0;
691}
692
3af9a47b 693int
116c20d2
NC
694bfd_mach_o_scan_read_symtab_symbol (bfd *abfd,
695 bfd_mach_o_symtab_command *sym,
696 asymbol *s,
697 unsigned long i)
3af9a47b
NC
698{
699 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
700 bfd_vma symoff = sym->symoff + (i * 12);
701 unsigned char buf[12];
702 unsigned char type = -1;
703 unsigned char section = -1;
704 short desc = -1;
e84d6fca 705 unsigned long value = -1;
3af9a47b
NC
706 unsigned long stroff = -1;
707 unsigned int symtype = -1;
708
709 BFD_ASSERT (sym->strtab != NULL);
710
711 bfd_seek (abfd, symoff, SEEK_SET);
712 if (bfd_bread ((PTR) buf, 12, abfd) != 12)
713 {
714 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: unable to read %d bytes at %lu\n",
715 12, (unsigned long) symoff);
716 return -1;
717 }
718
719 stroff = bfd_h_get_32 (abfd, buf);
720 type = bfd_h_get_8 (abfd, buf + 4);
721 symtype = (type & 0x0e);
722 section = bfd_h_get_8 (abfd, buf + 5) - 1;
723 desc = bfd_h_get_16 (abfd, buf + 6);
724 value = bfd_h_get_32 (abfd, buf + 8);
725
726 if (stroff >= sym->strsize)
727 {
728 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: symbol name out of range (%lu >= %lu)\n",
729 (unsigned long) stroff, (unsigned long) sym->strsize);
a95a4550 730 return -1;
3af9a47b
NC
731 }
732
733 s->the_bfd = abfd;
734 s->name = sym->strtab + stroff;
735 s->value = value;
736 s->udata.i = (type << 24) | (section << 16) | desc;
737 s->flags = 0x0;
738
739 if (type & BFD_MACH_O_N_STAB)
740 {
741 s->flags |= BSF_DEBUGGING;
742 s->section = bfd_und_section_ptr;
743 }
744 else
745 {
746 if (type & BFD_MACH_O_N_PEXT)
747 {
748 type &= ~BFD_MACH_O_N_PEXT;
749 s->flags |= BSF_GLOBAL;
750 }
751
752 if (type & BFD_MACH_O_N_EXT)
753 {
754 type &= ~BFD_MACH_O_N_EXT;
755 s->flags |= BSF_GLOBAL;
756 }
757
758 switch (symtype)
759 {
760 case BFD_MACH_O_N_UNDF:
761 s->section = bfd_und_section_ptr;
762 break;
763 case BFD_MACH_O_N_PBUD:
764 s->section = bfd_und_section_ptr;
765 break;
766 case BFD_MACH_O_N_ABS:
767 s->section = bfd_abs_section_ptr;
768 break;
769 case BFD_MACH_O_N_SECT:
770 if ((section > 0) && (section <= mdata->nsects))
771 {
772 s->section = mdata->sections[section - 1]->bfdsection;
773 s->value = s->value - mdata->sections[section - 1]->addr;
774 }
775 else
776 {
777 /* Mach-O uses 0 to mean "no section"; not an error. */
778 if (section != 0)
779 {
780 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
a95a4550 781 "symbol \"%s\" specified invalid section %d (max %lu): setting to undefined\n",
3af9a47b
NC
782 s->name, section, mdata->nsects);
783 }
784 s->section = bfd_und_section_ptr;
785 }
786 break;
787 case BFD_MACH_O_N_INDR:
788 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
a95a4550 789 "symbol \"%s\" is unsupported 'indirect' reference: setting to undefined\n",
3af9a47b
NC
790 s->name);
791 s->section = bfd_und_section_ptr;
792 break;
793 default:
794 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
a95a4550 795 "symbol \"%s\" specified invalid type field 0x%x: setting to undefined\n",
3af9a47b
NC
796 s->name, symtype);
797 s->section = bfd_und_section_ptr;
798 break;
799 }
800 }
801
802 return 0;
803}
804
805int
116c20d2
NC
806bfd_mach_o_scan_read_symtab_strtab (bfd *abfd,
807 bfd_mach_o_symtab_command *sym)
3af9a47b
NC
808{
809 BFD_ASSERT (sym->strtab == NULL);
810
811 if (abfd->flags & BFD_IN_MEMORY)
812 {
813 struct bfd_in_memory *b;
814
815 b = (struct bfd_in_memory *) abfd->iostream;
816
817 if ((sym->stroff + sym->strsize) > b->size)
818 {
819 bfd_set_error (bfd_error_file_truncated);
820 return -1;
821 }
f075ee0c 822 sym->strtab = (char *) b->buffer + sym->stroff;
3af9a47b
NC
823 return 0;
824 }
825
826 sym->strtab = bfd_alloc (abfd, sym->strsize);
827 if (sym->strtab == NULL)
828 return -1;
829
830 bfd_seek (abfd, sym->stroff, SEEK_SET);
831 if (bfd_bread ((PTR) sym->strtab, sym->strsize, abfd) != sym->strsize)
832 {
833 fprintf (stderr, "bfd_mach_o_scan_read_symtab_strtab: unable to read %lu bytes at %lu\n",
834 sym->strsize, sym->stroff);
a95a4550 835 return -1;
3af9a47b
NC
836 }
837
838 return 0;
839}
840
a95a4550 841int
116c20d2
NC
842bfd_mach_o_scan_read_symtab_symbols (bfd *abfd,
843 bfd_mach_o_symtab_command *sym)
3af9a47b
NC
844{
845 unsigned long i;
846 int ret;
847
848 BFD_ASSERT (sym->symbols == NULL);
849 sym->symbols = bfd_alloc (abfd, sym->nsyms * sizeof (asymbol));
850
851 if (sym->symbols == NULL)
852 {
853 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbols: unable to allocate memory for symbols\n");
a95a4550 854 return -1;
3af9a47b 855 }
a95a4550 856
3af9a47b
NC
857 ret = bfd_mach_o_scan_read_symtab_strtab (abfd, sym);
858 if (ret != 0)
859 return ret;
860
861 for (i = 0; i < sym->nsyms; i++)
862 {
863 ret = bfd_mach_o_scan_read_symtab_symbol (abfd, sym, &sym->symbols[i], i);
864 if (ret != 0)
865 return ret;
866 }
a95a4550 867
3af9a47b
NC
868 return 0;
869}
870
871int
116c20d2
NC
872bfd_mach_o_scan_read_dysymtab_symbol (bfd *abfd,
873 bfd_mach_o_dysymtab_command *dysym,
874 bfd_mach_o_symtab_command *sym,
875 asymbol *s,
876 unsigned long i)
3af9a47b
NC
877{
878 unsigned long isymoff = dysym->indirectsymoff + (i * 4);
879 unsigned long symindex;
880 unsigned char buf[4];
881
882 BFD_ASSERT (i < dysym->nindirectsyms);
a95a4550 883
3af9a47b
NC
884 bfd_seek (abfd, isymoff, SEEK_SET);
885 if (bfd_bread ((PTR) buf, 4, abfd) != 4)
886 {
887 fprintf (stderr, "bfd_mach_o_scan_read_dysymtab_symbol: unable to read %lu bytes at %lu\n",
888 (unsigned long) 4, isymoff);
889 return -1;
890 }
891 symindex = bfd_h_get_32 (abfd, buf);
a95a4550 892
3af9a47b
NC
893 return bfd_mach_o_scan_read_symtab_symbol (abfd, sym, s, symindex);
894}
895
896static const char *
116c20d2 897bfd_mach_o_i386_flavour_string (unsigned int flavour)
3af9a47b
NC
898{
899 switch ((int) flavour)
900 {
901 case BFD_MACH_O_i386_NEW_THREAD_STATE: return "i386_NEW_THREAD_STATE";
902 case BFD_MACH_O_i386_FLOAT_STATE: return "i386_FLOAT_STATE";
903 case BFD_MACH_O_i386_ISA_PORT_MAP_STATE: return "i386_ISA_PORT_MAP_STATE";
904 case BFD_MACH_O_i386_V86_ASSIST_STATE: return "i386_V86_ASSIST_STATE";
905 case BFD_MACH_O_i386_REGS_SEGS_STATE: return "i386_REGS_SEGS_STATE";
906 case BFD_MACH_O_i386_THREAD_SYSCALL_STATE: return "i386_THREAD_SYSCALL_STATE";
907 case BFD_MACH_O_i386_THREAD_STATE_NONE: return "i386_THREAD_STATE_NONE";
908 case BFD_MACH_O_i386_SAVED_STATE: return "i386_SAVED_STATE";
909 case BFD_MACH_O_i386_THREAD_STATE: return "i386_THREAD_STATE";
910 case BFD_MACH_O_i386_THREAD_FPSTATE: return "i386_THREAD_FPSTATE";
911 case BFD_MACH_O_i386_THREAD_EXCEPTSTATE: return "i386_THREAD_EXCEPTSTATE";
912 case BFD_MACH_O_i386_THREAD_CTHREADSTATE: return "i386_THREAD_CTHREADSTATE";
913 default: return "UNKNOWN";
914 }
915}
916
917static const char *
116c20d2 918bfd_mach_o_ppc_flavour_string (unsigned int flavour)
3af9a47b
NC
919{
920 switch ((int) flavour)
921 {
922 case BFD_MACH_O_PPC_THREAD_STATE: return "PPC_THREAD_STATE";
923 case BFD_MACH_O_PPC_FLOAT_STATE: return "PPC_FLOAT_STATE";
924 case BFD_MACH_O_PPC_EXCEPTION_STATE: return "PPC_EXCEPTION_STATE";
925 case BFD_MACH_O_PPC_VECTOR_STATE: return "PPC_VECTOR_STATE";
926 default: return "UNKNOWN";
927 }
928}
929
930static int
116c20d2
NC
931bfd_mach_o_scan_read_dylinker (bfd *abfd,
932 bfd_mach_o_load_command *command)
3af9a47b
NC
933{
934 bfd_mach_o_dylinker_command *cmd = &command->command.dylinker;
935 unsigned char buf[4];
936 unsigned int nameoff;
937 asection *bfdsec;
938 char *sname;
939 const char *prefix;
940
941 BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLINKER)
942 || (command->type == BFD_MACH_O_LC_LOAD_DYLINKER));
943
944 bfd_seek (abfd, command->offset + 8, SEEK_SET);
945 if (bfd_bread ((PTR) buf, 4, abfd) != 4)
946 return -1;
947
948 nameoff = bfd_h_get_32 (abfd, buf + 0);
949
950 cmd->name_offset = command->offset + nameoff;
951 cmd->name_len = command->len - nameoff;
952
953 if (command->type == BFD_MACH_O_LC_LOAD_DYLINKER)
954 prefix = "LC_LOAD_DYLINKER";
955 else if (command->type == BFD_MACH_O_LC_ID_DYLINKER)
956 prefix = "LC_ID_DYLINKER";
957 else
958 abort ();
959
116c20d2 960 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
961 if (sname == NULL)
962 return -1;
963 strcpy (sname, prefix);
964
117ed4f8 965 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
3af9a47b
NC
966 if (bfdsec == NULL)
967 return -1;
a95a4550 968
3af9a47b
NC
969 bfdsec->vma = 0;
970 bfdsec->lma = 0;
eea6121a 971 bfdsec->size = command->len - 8;
3af9a47b
NC
972 bfdsec->filepos = command->offset + 8;
973 bfdsec->alignment_power = 0;
3af9a47b
NC
974
975 cmd->section = bfdsec;
976
977 return 0;
978}
979
980static int
116c20d2 981bfd_mach_o_scan_read_dylib (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
982{
983 bfd_mach_o_dylib_command *cmd = &command->command.dylib;
984 unsigned char buf[16];
985 unsigned int nameoff;
986 asection *bfdsec;
987 char *sname;
988 const char *prefix;
989
990 BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLIB)
991 || (command->type == BFD_MACH_O_LC_LOAD_DYLIB)
992 || (command->type == BFD_MACH_O_LC_LOAD_WEAK_DYLIB));
993
994 bfd_seek (abfd, command->offset + 8, SEEK_SET);
995 if (bfd_bread ((PTR) buf, 16, abfd) != 16)
996 return -1;
997
998 nameoff = bfd_h_get_32 (abfd, buf + 0);
999 cmd->timestamp = bfd_h_get_32 (abfd, buf + 4);
1000 cmd->current_version = bfd_h_get_32 (abfd, buf + 8);
1001 cmd->compatibility_version = bfd_h_get_32 (abfd, buf + 12);
1002
1003 cmd->name_offset = command->offset + nameoff;
1004 cmd->name_len = command->len - nameoff;
1005
1006 if (command->type == BFD_MACH_O_LC_LOAD_DYLIB)
1007 prefix = "LC_LOAD_DYLIB";
1008 else if (command->type == BFD_MACH_O_LC_LOAD_WEAK_DYLIB)
1009 prefix = "LC_LOAD_WEAK_DYLIB";
1010 else if (command->type == BFD_MACH_O_LC_ID_DYLIB)
1011 prefix = "LC_ID_DYLIB";
1012 else
1013 abort ();
1014
116c20d2 1015 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
1016 if (sname == NULL)
1017 return -1;
1018 strcpy (sname, prefix);
1019
117ed4f8 1020 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
3af9a47b
NC
1021 if (bfdsec == NULL)
1022 return -1;
a95a4550 1023
3af9a47b
NC
1024 bfdsec->vma = 0;
1025 bfdsec->lma = 0;
eea6121a 1026 bfdsec->size = command->len - 8;
3af9a47b
NC
1027 bfdsec->filepos = command->offset + 8;
1028 bfdsec->alignment_power = 0;
3af9a47b
NC
1029
1030 cmd->section = bfdsec;
1031
1032 return 0;
1033}
1034
1035static int
116c20d2
NC
1036bfd_mach_o_scan_read_prebound_dylib (bfd *abfd ATTRIBUTE_UNUSED,
1037 bfd_mach_o_load_command *command ATTRIBUTE_UNUSED)
3af9a47b
NC
1038{
1039 /* bfd_mach_o_prebound_dylib_command *cmd = &command->command.prebound_dylib; */
1040
1041 BFD_ASSERT (command->type == BFD_MACH_O_LC_PREBOUND_DYLIB);
1042 return 0;
1043}
1044
1045static int
116c20d2 1046bfd_mach_o_scan_read_thread (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1047{
1048 bfd_mach_o_data_struct *mdata = NULL;
1049 bfd_mach_o_thread_command *cmd = &command->command.thread;
1050 unsigned char buf[8];
1051 bfd_vma offset;
1052 unsigned int nflavours;
1053 unsigned int i;
1054
1055 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
1056 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
1057
1058 BFD_ASSERT (bfd_mach_o_valid (abfd));
1059 mdata = abfd->tdata.mach_o_data;
a95a4550 1060
3af9a47b
NC
1061 offset = 8;
1062 nflavours = 0;
1063 while (offset != command->len)
1064 {
1065 if (offset >= command->len)
1066 return -1;
1067
1068 bfd_seek (abfd, command->offset + offset, SEEK_SET);
1069
1070 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
1071 return -1;
1072
1073 offset += 8 + bfd_h_get_32 (abfd, buf + 4) * 4;
1074 nflavours++;
1075 }
1076
116c20d2 1077 cmd->flavours = bfd_alloc (abfd, nflavours * sizeof (bfd_mach_o_thread_flavour));
3af9a47b
NC
1078 if (cmd->flavours == NULL)
1079 return -1;
1080 cmd->nflavours = nflavours;
1081
1082 offset = 8;
1083 nflavours = 0;
1084 while (offset != command->len)
1085 {
1086 if (offset >= command->len)
1087 return -1;
1088
1089 if (nflavours >= cmd->nflavours)
1090 return -1;
1091
1092 bfd_seek (abfd, command->offset + offset, SEEK_SET);
1093
1094 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
1095 return -1;
1096
1097 cmd->flavours[nflavours].flavour = bfd_h_get_32 (abfd, buf);
1098 cmd->flavours[nflavours].offset = command->offset + offset + 8;
1099 cmd->flavours[nflavours].size = bfd_h_get_32 (abfd, buf + 4) * 4;
1100 offset += cmd->flavours[nflavours].size + 8;
1101 nflavours++;
1102 }
1103
1104 for (i = 0; i < nflavours; i++)
1105 {
1106 asection *bfdsec;
1107 unsigned int snamelen;
1108 char *sname;
1109 const char *flavourstr;
1110 const char *prefix = "LC_THREAD";
a95a4550
AM
1111 unsigned int j = 0;
1112
3af9a47b
NC
1113 switch (mdata->header.cputype)
1114 {
1115 case BFD_MACH_O_CPU_TYPE_POWERPC:
1116 flavourstr = bfd_mach_o_ppc_flavour_string (cmd->flavours[i].flavour);
1117 break;
1118 case BFD_MACH_O_CPU_TYPE_I386:
1119 flavourstr = bfd_mach_o_i386_flavour_string (cmd->flavours[i].flavour);
1120 break;
1121 default:
1122 flavourstr = "UNKNOWN_ARCHITECTURE";
1123 break;
1124 }
a95a4550 1125
3af9a47b 1126 snamelen = strlen (prefix) + 1 + 20 + 1 + strlen (flavourstr) + 1;
116c20d2 1127 sname = bfd_alloc (abfd, snamelen);
3af9a47b
NC
1128 if (sname == NULL)
1129 return -1;
1130
1131 for (;;)
1132 {
a95a4550
AM
1133 sprintf (sname, "%s.%s.%u", prefix, flavourstr, j);
1134 if (bfd_get_section_by_name (abfd, sname) == NULL)
3af9a47b 1135 break;
a95a4550 1136 j++;
3af9a47b
NC
1137 }
1138
117ed4f8 1139 bfdsec = bfd_make_section_with_flags (abfd, sname, SEC_HAS_CONTENTS);
a95a4550 1140
3af9a47b
NC
1141 bfdsec->vma = 0;
1142 bfdsec->lma = 0;
eea6121a 1143 bfdsec->size = cmd->flavours[i].size;
3af9a47b
NC
1144 bfdsec->filepos = cmd->flavours[i].offset;
1145 bfdsec->alignment_power = 0x0;
3af9a47b
NC
1146
1147 cmd->section = bfdsec;
1148 }
1149
1150 return 0;
1151}
1152
a95a4550 1153static int
116c20d2 1154bfd_mach_o_scan_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1155{
1156 bfd_mach_o_dysymtab_command *seg = &command->command.dysymtab;
1157 unsigned char buf[72];
1158
1159 BFD_ASSERT (command->type == BFD_MACH_O_LC_DYSYMTAB);
1160
1161 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1162 if (bfd_bread ((PTR) buf, 72, abfd) != 72)
1163 return -1;
1164
1165 seg->ilocalsym = bfd_h_get_32 (abfd, buf + 0);
1166 seg->nlocalsym = bfd_h_get_32 (abfd, buf + 4);
1167 seg->iextdefsym = bfd_h_get_32 (abfd, buf + 8);
1168 seg->nextdefsym = bfd_h_get_32 (abfd, buf + 12);
1169 seg->iundefsym = bfd_h_get_32 (abfd, buf + 16);
1170 seg->nundefsym = bfd_h_get_32 (abfd, buf + 20);
1171 seg->tocoff = bfd_h_get_32 (abfd, buf + 24);
1172 seg->ntoc = bfd_h_get_32 (abfd, buf + 28);
1173 seg->modtaboff = bfd_h_get_32 (abfd, buf + 32);
1174 seg->nmodtab = bfd_h_get_32 (abfd, buf + 36);
1175 seg->extrefsymoff = bfd_h_get_32 (abfd, buf + 40);
1176 seg->nextrefsyms = bfd_h_get_32 (abfd, buf + 44);
1177 seg->indirectsymoff = bfd_h_get_32 (abfd, buf + 48);
1178 seg->nindirectsyms = bfd_h_get_32 (abfd, buf + 52);
1179 seg->extreloff = bfd_h_get_32 (abfd, buf + 56);
1180 seg->nextrel = bfd_h_get_32 (abfd, buf + 60);
1181 seg->locreloff = bfd_h_get_32 (abfd, buf + 64);
1182 seg->nlocrel = bfd_h_get_32 (abfd, buf + 68);
1183
1184 return 0;
1185}
1186
a95a4550 1187static int
116c20d2 1188bfd_mach_o_scan_read_symtab (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1189{
1190 bfd_mach_o_symtab_command *seg = &command->command.symtab;
1191 unsigned char buf[16];
1192 asection *bfdsec;
1193 char *sname;
1194 const char *prefix = "LC_SYMTAB.stabs";
1195
1196 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
1197
1198 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1199 if (bfd_bread ((PTR) buf, 16, abfd) != 16)
1200 return -1;
a95a4550 1201
3af9a47b
NC
1202 seg->symoff = bfd_h_get_32 (abfd, buf);
1203 seg->nsyms = bfd_h_get_32 (abfd, buf + 4);
1204 seg->stroff = bfd_h_get_32 (abfd, buf + 8);
1205 seg->strsize = bfd_h_get_32 (abfd, buf + 12);
1206 seg->symbols = NULL;
1207 seg->strtab = NULL;
1208
116c20d2 1209 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
1210 if (sname == NULL)
1211 return -1;
1212 strcpy (sname, prefix);
1213
117ed4f8 1214 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
3af9a47b
NC
1215 if (bfdsec == NULL)
1216 return -1;
a95a4550 1217
3af9a47b
NC
1218 bfdsec->vma = 0;
1219 bfdsec->lma = 0;
eea6121a 1220 bfdsec->size = seg->nsyms * 12;
3af9a47b
NC
1221 bfdsec->filepos = seg->symoff;
1222 bfdsec->alignment_power = 0;
3af9a47b
NC
1223
1224 seg->stabs_segment = bfdsec;
1225
1226 prefix = "LC_SYMTAB.stabstr";
116c20d2 1227 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
1228 if (sname == NULL)
1229 return -1;
1230 strcpy (sname, prefix);
1231
117ed4f8 1232 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
3af9a47b
NC
1233 if (bfdsec == NULL)
1234 return -1;
a95a4550 1235
3af9a47b
NC
1236 bfdsec->vma = 0;
1237 bfdsec->lma = 0;
eea6121a 1238 bfdsec->size = seg->strsize;
3af9a47b
NC
1239 bfdsec->filepos = seg->stroff;
1240 bfdsec->alignment_power = 0;
3af9a47b
NC
1241
1242 seg->stabstr_segment = bfdsec;
1243
1244 return 0;
1245}
1246
1247static int
116c20d2 1248bfd_mach_o_scan_read_segment (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1249{
1250 unsigned char buf[48];
1251 bfd_mach_o_segment_command *seg = &command->command.segment;
1252 unsigned long i;
1253 asection *bfdsec;
1254 char *sname;
1255 const char *prefix = "LC_SEGMENT";
1256 unsigned int snamelen;
117ed4f8 1257 flagword flags;
a95a4550 1258
3af9a47b
NC
1259 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
1260
1261 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1262 if (bfd_bread ((PTR) buf, 48, abfd) != 48)
1263 return -1;
1264
1265 memcpy (seg->segname, buf, 16);
1266 seg->vmaddr = bfd_h_get_32 (abfd, buf + 16);
1267 seg->vmsize = bfd_h_get_32 (abfd, buf + 20);
1268 seg->fileoff = bfd_h_get_32 (abfd, buf + 24);
1269 seg->filesize = bfd_h_get_32 (abfd, buf + 28);
1270 /* seg->maxprot = bfd_h_get_32 (abfd, buf + 32); */
1271 /* seg->initprot = bfd_h_get_32 (abfd, buf + 36); */
1272 seg->nsects = bfd_h_get_32 (abfd, buf + 40);
1273 seg->flags = bfd_h_get_32 (abfd, buf + 44);
1274
1275 snamelen = strlen (prefix) + 1 + strlen (seg->segname) + 1;
116c20d2 1276 sname = bfd_alloc (abfd, snamelen);
3af9a47b
NC
1277 if (sname == NULL)
1278 return -1;
1279 sprintf (sname, "%s.%s", prefix, seg->segname);
1280
117ed4f8
AM
1281 flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE;
1282 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, flags);
3af9a47b
NC
1283 if (bfdsec == NULL)
1284 return -1;
1285
1286 bfdsec->vma = seg->vmaddr;
1287 bfdsec->lma = seg->vmaddr;
eea6121a 1288 bfdsec->size = seg->filesize;
3af9a47b
NC
1289 bfdsec->filepos = seg->fileoff;
1290 bfdsec->alignment_power = 0x0;
3af9a47b
NC
1291
1292 seg->segment = bfdsec;
1293
1294 if (seg->nsects != 0)
1295 {
116c20d2 1296 seg->sections = bfd_alloc (abfd, seg->nsects * sizeof (bfd_mach_o_section));
3af9a47b
NC
1297 if (seg->sections == NULL)
1298 return -1;
a95a4550 1299
3af9a47b
NC
1300 for (i = 0; i < seg->nsects; i++)
1301 {
1302 bfd_vma segoff = command->offset + 48 + 8 + (i * 68);
1303
e84d6fca
AM
1304 if (bfd_mach_o_scan_read_section (abfd, &seg->sections[i],
1305 segoff) != 0)
3af9a47b 1306 return -1;
a95a4550 1307 }
3af9a47b
NC
1308 }
1309
1310 return 0;
1311}
1312
1313static int
116c20d2 1314bfd_mach_o_scan_read_command (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1315{
1316 unsigned char buf[8];
1317
1318 bfd_seek (abfd, command->offset, SEEK_SET);
1319 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
1320 return -1;
1321
1322 command->type = (bfd_h_get_32 (abfd, buf) & ~BFD_MACH_O_LC_REQ_DYLD);
e84d6fca
AM
1323 command->type_required = (bfd_h_get_32 (abfd, buf) & BFD_MACH_O_LC_REQ_DYLD
1324 ? 1 : 0);
3af9a47b
NC
1325 command->len = bfd_h_get_32 (abfd, buf + 4);
1326
1327 switch (command->type)
1328 {
1329 case BFD_MACH_O_LC_SEGMENT:
1330 if (bfd_mach_o_scan_read_segment (abfd, command) != 0)
1331 return -1;
1332 break;
1333 case BFD_MACH_O_LC_SYMTAB:
1334 if (bfd_mach_o_scan_read_symtab (abfd, command) != 0)
1335 return -1;
1336 break;
1337 case BFD_MACH_O_LC_SYMSEG:
1338 break;
1339 case BFD_MACH_O_LC_THREAD:
1340 case BFD_MACH_O_LC_UNIXTHREAD:
1341 if (bfd_mach_o_scan_read_thread (abfd, command) != 0)
1342 return -1;
1343 break;
1344 case BFD_MACH_O_LC_LOAD_DYLINKER:
1345 case BFD_MACH_O_LC_ID_DYLINKER:
1346 if (bfd_mach_o_scan_read_dylinker (abfd, command) != 0)
1347 return -1;
1348 break;
1349 case BFD_MACH_O_LC_LOAD_DYLIB:
1350 case BFD_MACH_O_LC_ID_DYLIB:
1351 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
1352 if (bfd_mach_o_scan_read_dylib (abfd, command) != 0)
1353 return -1;
1354 break;
1355 case BFD_MACH_O_LC_PREBOUND_DYLIB:
1356 if (bfd_mach_o_scan_read_prebound_dylib (abfd, command) != 0)
1357 return -1;
1358 break;
1359 case BFD_MACH_O_LC_LOADFVMLIB:
1360 case BFD_MACH_O_LC_IDFVMLIB:
1361 case BFD_MACH_O_LC_IDENT:
1362 case BFD_MACH_O_LC_FVMFILE:
1363 case BFD_MACH_O_LC_PREPAGE:
1364 case BFD_MACH_O_LC_ROUTINES:
1365 case BFD_MACH_O_LC_SUB_FRAMEWORK:
1366 break;
1367 case BFD_MACH_O_LC_DYSYMTAB:
1368 if (bfd_mach_o_scan_read_dysymtab (abfd, command) != 0)
1369 return -1;
1370 break;
1371 case BFD_MACH_O_LC_SUB_UMBRELLA:
1372 case BFD_MACH_O_LC_SUB_CLIENT:
1373 case BFD_MACH_O_LC_SUB_LIBRARY:
1374 case BFD_MACH_O_LC_TWOLEVEL_HINTS:
1375 case BFD_MACH_O_LC_PREBIND_CKSUM:
1376 break;
1377 default:
1378 fprintf (stderr, "unable to read unknown load command 0x%lx\n",
1379 (unsigned long) command->type);
1380 break;
1381 }
1382
1383 return 0;
1384}
1385
1386static void
116c20d2 1387bfd_mach_o_flatten_sections (bfd *abfd)
3af9a47b
NC
1388{
1389 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
1390 long csect = 0;
1391 unsigned long i, j;
a95a4550 1392
3af9a47b
NC
1393 mdata->nsects = 0;
1394
1395 for (i = 0; i < mdata->header.ncmds; i++)
1396 {
1397 if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT)
1398 {
e84d6fca
AM
1399 bfd_mach_o_segment_command *seg;
1400
1401 seg = &mdata->commands[i].command.segment;
3af9a47b
NC
1402 mdata->nsects += seg->nsects;
1403 }
1404 }
1405
e84d6fca
AM
1406 mdata->sections = bfd_alloc (abfd,
1407 mdata->nsects * sizeof (bfd_mach_o_section *));
3af9a47b
NC
1408 csect = 0;
1409
1410 for (i = 0; i < mdata->header.ncmds; i++)
1411 {
1412 if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT)
1413 {
e84d6fca 1414 bfd_mach_o_segment_command *seg;
3af9a47b 1415
e84d6fca 1416 seg = &mdata->commands[i].command.segment;
3af9a47b
NC
1417 BFD_ASSERT (csect + seg->nsects <= mdata->nsects);
1418
1419 for (j = 0; j < seg->nsects; j++)
1420 mdata->sections[csect++] = &seg->sections[j];
1421 }
1422 }
1423}
1424
1425int
116c20d2 1426bfd_mach_o_scan_start_address (bfd *abfd)
3af9a47b
NC
1427{
1428 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
1429 bfd_mach_o_thread_command *cmd = NULL;
1430 unsigned long i;
1431
1432 for (i = 0; i < mdata->header.ncmds; i++)
1433 {
1434 if ((mdata->commands[i].type == BFD_MACH_O_LC_THREAD) ||
1435 (mdata->commands[i].type == BFD_MACH_O_LC_UNIXTHREAD))
1436 {
1437 if (cmd == NULL)
1438 cmd = &mdata->commands[i].command.thread;
1439 else
1440 return 0;
1441 }
1442 }
1443
1444 if (cmd == NULL)
1445 return 0;
1446
1447 for (i = 0; i < cmd->nflavours; i++)
1448 {
a95a4550 1449 if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_I386)
e84d6fca
AM
1450 && (cmd->flavours[i].flavour
1451 == (unsigned long) BFD_MACH_O_i386_THREAD_STATE))
3af9a47b
NC
1452 {
1453 unsigned char buf[4];
1454
1455 bfd_seek (abfd, cmd->flavours[i].offset + 40, SEEK_SET);
1456
1457 if (bfd_bread (buf, 4, abfd) != 4)
1458 return -1;
1459
1460 abfd->start_address = bfd_h_get_32 (abfd, buf);
1461 }
a95a4550 1462 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC)
3af9a47b
NC
1463 && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE))
1464 {
1465 unsigned char buf[4];
1466
1467 bfd_seek (abfd, cmd->flavours[i].offset + 0, SEEK_SET);
1468
1469 if (bfd_bread (buf, 4, abfd) != 4)
1470 return -1;
1471
1472 abfd->start_address = bfd_h_get_32 (abfd, buf);
1473 }
1474 }
1475
1476 return 0;
1477}
1478
1479int
116c20d2
NC
1480bfd_mach_o_scan (bfd *abfd,
1481 bfd_mach_o_header *header,
1482 bfd_mach_o_data_struct *mdata)
3af9a47b
NC
1483{
1484 unsigned int i;
3af9a47b
NC
1485 enum bfd_architecture cputype;
1486 unsigned long cpusubtype;
1487
3af9a47b
NC
1488 mdata->header = *header;
1489 mdata->symbols = NULL;
1490
e84d6fca
AM
1491 abfd->flags = (abfd->xvec->object_flags
1492 | (abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS)));
3af9a47b
NC
1493 abfd->tdata.mach_o_data = mdata;
1494
e84d6fca
AM
1495 bfd_mach_o_convert_architecture (header->cputype, header->cpusubtype,
1496 &cputype, &cpusubtype);
3af9a47b
NC
1497 if (cputype == bfd_arch_unknown)
1498 {
1499 fprintf (stderr, "bfd_mach_o_scan: unknown architecture 0x%lx/0x%lx\n",
1500 header->cputype, header->cpusubtype);
1501 return -1;
1502 }
1503
1504 bfd_set_arch_mach (abfd, cputype, cpusubtype);
a95a4550 1505
3af9a47b
NC
1506 if (header->ncmds != 0)
1507 {
116c20d2 1508 mdata->commands = bfd_alloc (abfd, header->ncmds * sizeof (bfd_mach_o_load_command));
3af9a47b
NC
1509 if (mdata->commands == NULL)
1510 return -1;
a95a4550 1511
3af9a47b
NC
1512 for (i = 0; i < header->ncmds; i++)
1513 {
1514 bfd_mach_o_load_command *cur = &mdata->commands[i];
1515
1516 if (i == 0)
1517 cur->offset = 28;
1518 else
1519 {
1520 bfd_mach_o_load_command *prev = &mdata->commands[i - 1];
1521 cur->offset = prev->offset + prev->len;
1522 }
1523
1524 if (bfd_mach_o_scan_read_command (abfd, cur) < 0)
1525 return -1;
a95a4550 1526 }
3af9a47b
NC
1527 }
1528
1529 if (bfd_mach_o_scan_start_address (abfd) < 0)
7e3102a7 1530 return -1;
3af9a47b
NC
1531
1532 bfd_mach_o_flatten_sections (abfd);
3af9a47b
NC
1533 return 0;
1534}
1535
b34976b6 1536bfd_boolean
116c20d2 1537bfd_mach_o_mkobject (bfd *abfd)
3af9a47b
NC
1538{
1539 bfd_mach_o_data_struct *mdata = NULL;
1540
116c20d2 1541 mdata = bfd_alloc (abfd, sizeof (bfd_mach_o_data_struct));
3af9a47b 1542 if (mdata == NULL)
b34976b6 1543 return FALSE;
3af9a47b
NC
1544 abfd->tdata.mach_o_data = mdata;
1545
1546 mdata->header.magic = 0;
1547 mdata->header.cputype = 0;
1548 mdata->header.cpusubtype = 0;
1549 mdata->header.filetype = 0;
1550 mdata->header.ncmds = 0;
1551 mdata->header.sizeofcmds = 0;
1552 mdata->header.flags = 0;
1553 mdata->header.byteorder = BFD_ENDIAN_UNKNOWN;
1554 mdata->commands = NULL;
1555 mdata->nsymbols = 0;
1556 mdata->symbols = NULL;
1557 mdata->nsects = 0;
1558 mdata->sections = NULL;
1559 mdata->ibfd = NULL;
1560
b34976b6 1561 return TRUE;
3af9a47b
NC
1562}
1563
1564const bfd_target *
116c20d2 1565bfd_mach_o_object_p (bfd *abfd)
3af9a47b 1566{
e84d6fca 1567 struct bfd_preserve preserve;
3af9a47b
NC
1568 bfd_mach_o_header header;
1569
e84d6fca 1570 preserve.marker = NULL;
3af9a47b 1571 if (bfd_mach_o_read_header (abfd, &header) != 0)
e84d6fca 1572 goto wrong;
3af9a47b 1573
e84d6fca
AM
1574 if (! (header.byteorder == BFD_ENDIAN_BIG
1575 || header.byteorder == BFD_ENDIAN_LITTLE))
3af9a47b 1576 {
e84d6fca
AM
1577 fprintf (stderr, "unknown header byte-order value 0x%lx\n",
1578 (long) header.byteorder);
1579 goto wrong;
3af9a47b
NC
1580 }
1581
e84d6fca
AM
1582 if (! ((header.byteorder == BFD_ENDIAN_BIG
1583 && abfd->xvec->byteorder == BFD_ENDIAN_BIG
1584 && abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
1585 || (header.byteorder == BFD_ENDIAN_LITTLE
1586 && abfd->xvec->byteorder == BFD_ENDIAN_LITTLE
1587 && abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)))
1588 goto wrong;
3af9a47b 1589
e84d6fca
AM
1590 preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct));
1591 if (preserve.marker == NULL
1592 || !bfd_preserve_save (abfd, &preserve))
1593 goto fail;
3af9a47b 1594
e84d6fca
AM
1595 if (bfd_mach_o_scan (abfd, &header,
1596 (bfd_mach_o_data_struct *) preserve.marker) != 0)
1597 goto wrong;
a95a4550 1598
e84d6fca 1599 bfd_preserve_finish (abfd, &preserve);
3af9a47b 1600 return abfd->xvec;
e84d6fca
AM
1601
1602 wrong:
1603 bfd_set_error (bfd_error_wrong_format);
1604
1605 fail:
1606 if (preserve.marker != NULL)
1607 bfd_preserve_restore (abfd, &preserve);
1608 return NULL;
3af9a47b
NC
1609}
1610
1611const bfd_target *
116c20d2 1612bfd_mach_o_core_p (bfd *abfd)
3af9a47b 1613{
e84d6fca 1614 struct bfd_preserve preserve;
3af9a47b
NC
1615 bfd_mach_o_header header;
1616
e84d6fca 1617 preserve.marker = NULL;
3af9a47b 1618 if (bfd_mach_o_read_header (abfd, &header) != 0)
e84d6fca 1619 goto wrong;
3af9a47b 1620
e84d6fca
AM
1621 if (! (header.byteorder == BFD_ENDIAN_BIG
1622 || header.byteorder == BFD_ENDIAN_LITTLE))
3af9a47b 1623 {
e84d6fca
AM
1624 fprintf (stderr, "unknown header byte-order value 0x%lx\n",
1625 (long) header.byteorder);
3af9a47b
NC
1626 abort ();
1627 }
1628
e84d6fca
AM
1629 if (! ((header.byteorder == BFD_ENDIAN_BIG
1630 && abfd->xvec->byteorder == BFD_ENDIAN_BIG
1631 && abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
1632 || (header.byteorder == BFD_ENDIAN_LITTLE
1633 && abfd->xvec->byteorder == BFD_ENDIAN_LITTLE
1634 && abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)))
1635 goto wrong;
3af9a47b
NC
1636
1637 if (header.filetype != BFD_MACH_O_MH_CORE)
e84d6fca 1638 goto wrong;
3af9a47b 1639
e84d6fca
AM
1640 preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct));
1641 if (preserve.marker == NULL
1642 || !bfd_preserve_save (abfd, &preserve))
1643 goto fail;
a95a4550 1644
e84d6fca
AM
1645 if (bfd_mach_o_scan (abfd, &header,
1646 (bfd_mach_o_data_struct *) preserve.marker) != 0)
1647 goto wrong;
1648
1649 bfd_preserve_finish (abfd, &preserve);
3af9a47b 1650 return abfd->xvec;
e84d6fca
AM
1651
1652 wrong:
1653 bfd_set_error (bfd_error_wrong_format);
1654
1655 fail:
1656 if (preserve.marker != NULL)
1657 bfd_preserve_restore (abfd, &preserve);
1658 return NULL;
3af9a47b
NC
1659}
1660
1661typedef struct mach_o_fat_archentry
1662{
1663 unsigned long cputype;
1664 unsigned long cpusubtype;
1665 unsigned long offset;
1666 unsigned long size;
1667 unsigned long align;
1668 bfd *abfd;
1669} mach_o_fat_archentry;
1670
1671typedef struct mach_o_fat_data_struct
1672{
1673 unsigned long magic;
1674 unsigned long nfat_arch;
1675 mach_o_fat_archentry *archentries;
1676} mach_o_fat_data_struct;
1677
1678const bfd_target *
116c20d2 1679bfd_mach_o_archive_p (bfd *abfd)
3af9a47b 1680{
e84d6fca 1681 mach_o_fat_data_struct *adata = NULL;
3af9a47b
NC
1682 unsigned char buf[20];
1683 unsigned long i;
1684
1685 bfd_seek (abfd, 0, SEEK_SET);
1686 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
e84d6fca 1687 goto error;
3af9a47b 1688
116c20d2 1689 adata = bfd_alloc (abfd, sizeof (mach_o_fat_data_struct));
3af9a47b 1690 if (adata == NULL)
e84d6fca 1691 goto error;
a95a4550 1692
3af9a47b
NC
1693 adata->magic = bfd_getb32 (buf);
1694 adata->nfat_arch = bfd_getb32 (buf + 4);
1695 if (adata->magic != 0xcafebabe)
e84d6fca 1696 goto error;
3af9a47b 1697
116c20d2 1698 adata->archentries =
3af9a47b
NC
1699 bfd_alloc (abfd, adata->nfat_arch * sizeof (mach_o_fat_archentry));
1700 if (adata->archentries == NULL)
e84d6fca 1701 goto error;
3af9a47b
NC
1702
1703 for (i = 0; i < adata->nfat_arch; i++)
1704 {
1705 bfd_seek (abfd, 8 + 20 * i, SEEK_SET);
1706
1707 if (bfd_bread ((PTR) buf, 20, abfd) != 20)
e84d6fca 1708 goto error;
3af9a47b
NC
1709 adata->archentries[i].cputype = bfd_getb32 (buf);
1710 adata->archentries[i].cpusubtype = bfd_getb32 (buf + 4);
1711 adata->archentries[i].offset = bfd_getb32 (buf + 8);
1712 adata->archentries[i].size = bfd_getb32 (buf + 12);
1713 adata->archentries[i].align = bfd_getb32 (buf + 16);
1714 adata->archentries[i].abfd = NULL;
1715 }
1716
1717 abfd->tdata.mach_o_fat_data = adata;
1718 return abfd->xvec;
e84d6fca
AM
1719
1720 error:
1721 if (adata != NULL)
1722 bfd_release (abfd, adata);
1723 bfd_set_error (bfd_error_wrong_format);
1724 return NULL;
3af9a47b
NC
1725}
1726
1727bfd *
116c20d2 1728bfd_mach_o_openr_next_archived_file (bfd *archive, bfd *prev)
3af9a47b 1729{
e84d6fca 1730 mach_o_fat_data_struct *adata;
3af9a47b
NC
1731 mach_o_fat_archentry *entry = NULL;
1732 unsigned long i;
1733
e84d6fca 1734 adata = (mach_o_fat_data_struct *) archive->tdata.mach_o_fat_data;
3af9a47b
NC
1735 BFD_ASSERT (adata != NULL);
1736
1737 /* Find index of previous entry. */
1738 if (prev == NULL)
1739 i = 0; /* Start at first one. */
1740 else
1741 {
1742 for (i = 0; i < adata->nfat_arch; i++)
1743 {
1744 if (adata->archentries[i].abfd == prev)
1745 break;
1746 }
1747
1748 if (i == adata->nfat_arch)
1749 {
1750 /* Not found. */
1751 bfd_set_error (bfd_error_bad_value);
a95a4550 1752 return NULL;
3af9a47b
NC
1753 }
1754 i++; /* Get next entry. */
1755 }
a95a4550 1756
3af9a47b
NC
1757 if (i >= adata->nfat_arch)
1758 {
1759 bfd_set_error (bfd_error_no_more_archived_files);
1760 return NULL;
1761 }
1762
1763 entry = &adata->archentries[i];
1764 if (entry->abfd == NULL)
1765 {
1766 bfd *nbfd = _bfd_new_bfd_contained_in (archive);
1767 char *s = NULL;
1768
1769 if (nbfd == NULL)
1770 return NULL;
1771
1772 nbfd->origin = entry->offset;
1773 s = bfd_malloc (strlen (archive->filename) + 1);
1774 if (s == NULL)
1775 return NULL;
1776 strcpy (s, archive->filename);
1777 nbfd->filename = s;
1778 nbfd->iostream = NULL;
1779 entry->abfd = nbfd;
1780 }
1781
1782 return entry->abfd;
1783}
1784
e84d6fca 1785int
116c20d2
NC
1786bfd_mach_o_lookup_section (bfd *abfd,
1787 asection *section,
1788 bfd_mach_o_load_command **mcommand,
1789 bfd_mach_o_section **msection)
3af9a47b
NC
1790{
1791 struct mach_o_data_struct *md = abfd->tdata.mach_o_data;
1792 unsigned int i, j, num;
1793
1794 bfd_mach_o_load_command *ncmd = NULL;
1795 bfd_mach_o_section *nsect = NULL;
1796
1797 BFD_ASSERT (mcommand != NULL);
1798 BFD_ASSERT (msection != NULL);
1799
1800 num = 0;
1801 for (i = 0; i < md->header.ncmds; i++)
1802 {
1803 struct bfd_mach_o_load_command *cmd = &md->commands[i];
1804 struct bfd_mach_o_segment_command *seg = NULL;
1805
1806 if (cmd->type != BFD_MACH_O_LC_SEGMENT)
1807 continue;
1808 seg = &cmd->command.segment;
a95a4550 1809
3af9a47b
NC
1810 if (seg->segment == section)
1811 {
1812 if (num == 0)
1813 ncmd = cmd;
1814 num++;
1815 }
1816
1817 for (j = 0; j < seg->nsects; j++)
1818 {
1819 struct bfd_mach_o_section *sect = &seg->sections[j];
1820
1821 if (sect->bfdsection == section)
1822 {
1823 if (num == 0)
1824 nsect = sect;
1825 num++;
1826 }
1827 }
1828 }
a95a4550 1829
3af9a47b
NC
1830 *mcommand = ncmd;
1831 *msection = nsect;
1832 return num;
1833}
1834
1835int
116c20d2
NC
1836bfd_mach_o_lookup_command (bfd *abfd,
1837 bfd_mach_o_load_command_type type,
1838 bfd_mach_o_load_command **mcommand)
3af9a47b
NC
1839{
1840 struct mach_o_data_struct *md = NULL;
1841 bfd_mach_o_load_command *ncmd = NULL;
1842 unsigned int i, num;
1843
1844 md = abfd->tdata.mach_o_data;
1845
1846 BFD_ASSERT (md != NULL);
1847 BFD_ASSERT (mcommand != NULL);
1848
1849 num = 0;
1850 for (i = 0; i < md->header.ncmds; i++)
1851 {
1852 struct bfd_mach_o_load_command *cmd = &md->commands[i];
1853
1854 if (cmd->type != type)
1855 continue;
1856
1857 if (num == 0)
1858 ncmd = cmd;
1859 num++;
1860 }
1861
1862 *mcommand = ncmd;
1863 return num;
1864}
1865
1866unsigned long
116c20d2 1867bfd_mach_o_stack_addr (enum bfd_mach_o_cpu_type type)
3af9a47b
NC
1868{
1869 switch (type)
1870 {
1871 case BFD_MACH_O_CPU_TYPE_MC680x0:
1872 return 0x04000000;
1873 case BFD_MACH_O_CPU_TYPE_MC88000:
1874 return 0xffffe000;
1875 case BFD_MACH_O_CPU_TYPE_POWERPC:
1876 return 0xc0000000;
1877 case BFD_MACH_O_CPU_TYPE_I386:
1878 return 0xc0000000;
1879 case BFD_MACH_O_CPU_TYPE_SPARC:
1880 return 0xf0000000;
1881 case BFD_MACH_O_CPU_TYPE_I860:
1882 return 0;
1883 case BFD_MACH_O_CPU_TYPE_HPPA:
e84d6fca 1884 return 0xc0000000 - 0x04000000;
3af9a47b
NC
1885 default:
1886 return 0;
1887 }
1888}
1889
1890int
116c20d2
NC
1891bfd_mach_o_core_fetch_environment (bfd *abfd,
1892 unsigned char **rbuf,
1893 unsigned int *rlen)
3af9a47b
NC
1894{
1895 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
1896 unsigned long stackaddr = bfd_mach_o_stack_addr (mdata->header.cputype);
1897 unsigned int i = 0;
1898
1899 for (i = 0; i < mdata->header.ncmds; i++)
1900 {
1901 bfd_mach_o_load_command *cur = &mdata->commands[i];
1902 bfd_mach_o_segment_command *seg = NULL;
1903
1904 if (cur->type != BFD_MACH_O_LC_SEGMENT)
1905 continue;
1906
1907 seg = &cur->command.segment;
1908
1909 if ((seg->vmaddr + seg->vmsize) == stackaddr)
1910 {
1911 unsigned long start = seg->fileoff;
1912 unsigned long end = seg->fileoff + seg->filesize;
1913 unsigned char *buf = bfd_malloc (1024);
1914 unsigned long size = 1024;
1915
1916 for (;;)
1917 {
1918 bfd_size_type nread = 0;
1919 unsigned long offset;
1920 int found_nonnull = 0;
1921
1922 if (size > (end - start))
1923 size = (end - start);
1924
1925 buf = bfd_realloc (buf, size);
1926
1927 bfd_seek (abfd, end - size, SEEK_SET);
1928 nread = bfd_bread (buf, size, abfd);
a95a4550 1929
3af9a47b
NC
1930 if (nread != size)
1931 return -1;
a95a4550 1932
3af9a47b
NC
1933 for (offset = 4; offset <= size; offset += 4)
1934 {
e84d6fca 1935 unsigned long val;
3af9a47b 1936
e84d6fca 1937 val = *((unsigned long *) (buf + size - offset));
3af9a47b
NC
1938 if (! found_nonnull)
1939 {
1940 if (val != 0)
1941 found_nonnull = 1;
1942 }
1943 else if (val == 0x0)
1944 {
e84d6fca
AM
1945 unsigned long bottom;
1946 unsigned long top;
3af9a47b 1947
e84d6fca
AM
1948 bottom = seg->fileoff + seg->filesize - offset;
1949 top = seg->fileoff + seg->filesize - 4;
3af9a47b
NC
1950 *rbuf = bfd_malloc (top - bottom);
1951 *rlen = top - bottom;
1952
1953 memcpy (*rbuf, buf + size - *rlen, *rlen);
1954 return 0;
1955 }
1956 }
1957
1958 if (size == (end - start))
1959 break;
1960
1961 size *= 2;
1962 }
1963 }
1964 }
1965
1966 return -1;
1967}
1968
1969char *
116c20d2 1970bfd_mach_o_core_file_failing_command (bfd *abfd)
3af9a47b
NC
1971{
1972 unsigned char *buf = NULL;
1973 unsigned int len = 0;
1974 int ret = -1;
1975
1976 ret = bfd_mach_o_core_fetch_environment (abfd, &buf, &len);
1977 if (ret < 0)
1978 return NULL;
1979
f075ee0c 1980 return (char *) buf;
3af9a47b
NC
1981}
1982
1983int
116c20d2 1984bfd_mach_o_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
3af9a47b
NC
1985{
1986 return 0;
1987}
1988
116c20d2
NC
1989#define TARGET_NAME mach_o_be_vec
1990#define TARGET_STRING "mach-o-be"
1991#define TARGET_BIG_ENDIAN 1
1992#define TARGET_ARCHIVE 0
3af9a47b
NC
1993
1994#include "mach-o-target.c"
1995
1996#undef TARGET_NAME
1997#undef TARGET_STRING
1998#undef TARGET_BIG_ENDIAN
1999#undef TARGET_ARCHIVE
2000
116c20d2
NC
2001#define TARGET_NAME mach_o_le_vec
2002#define TARGET_STRING "mach-o-le"
2003#define TARGET_BIG_ENDIAN 0
2004#define TARGET_ARCHIVE 0
3af9a47b
NC
2005
2006#include "mach-o-target.c"
2007
2008#undef TARGET_NAME
2009#undef TARGET_STRING
2010#undef TARGET_BIG_ENDIAN
2011#undef TARGET_ARCHIVE
2012
116c20d2
NC
2013#define TARGET_NAME mach_o_fat_vec
2014#define TARGET_STRING "mach-o-fat"
2015#define TARGET_BIG_ENDIAN 1
2016#define TARGET_ARCHIVE 1
3af9a47b
NC
2017
2018#include "mach-o-target.c"
2019
2020#undef TARGET_NAME
2021#undef TARGET_STRING
2022#undef TARGET_BIG_ENDIAN
2023#undef TARGET_ARCHIVE
This page took 0.340806 seconds and 4 git commands to generate.