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