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