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