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