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