* i386-tdep.c (i386_reg_struct_return_p): Handle structures with a
[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
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
78
3af9a47b
NC
79
80/* The flags field of a section structure is separated into two parts a section
81 type and section attributes. The section types are mutually exclusive (it
82 can only have one type) but the section attributes are not (it may have more
83 than one attribute). */
84
85#define SECTION_TYPE 0x000000ff /* 256 section types. */
86#define SECTION_ATTRIBUTES 0xffffff00 /* 24 section attributes. */
87
88/* Constants for the section attributes part of the flags field of a section
89 structure. */
90
91#define SECTION_ATTRIBUTES_USR 0xff000000 /* User-settable attributes. */
92#define S_ATTR_PURE_INSTRUCTIONS 0x80000000 /* Section contains only true machine instructions. */
93#define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* System setable attributes. */
94#define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* Section contains some machine instructions. */
95#define S_ATTR_EXT_RELOC 0x00000200 /* Section has external relocation entries. */
96#define S_ATTR_LOC_RELOC 0x00000100 /* Section has local relocation entries. */
97
98#define N_STAB 0xe0
99#define N_TYPE 0x1e
100#define N_EXT 0x01
101#define N_UNDF 0x0
102#define N_ABS 0x2
103#define N_SECT 0xe
104#define N_INDR 0xa
105
b34976b6 106bfd_boolean
116c20d2 107bfd_mach_o_valid (bfd *abfd)
3af9a47b
NC
108{
109 if (abfd == NULL || abfd->xvec == NULL)
110 return 0;
111
112 if (! ((abfd->xvec == &mach_o_be_vec)
113 || (abfd->xvec == &mach_o_le_vec)
114 || (abfd->xvec == &mach_o_fat_vec)))
115 return 0;
116
117 if (abfd->tdata.mach_o_data == NULL)
118 return 0;
119 return 1;
120}
121
122/* Copy any private info we understand from the input symbol
123 to the output symbol. */
124
b34976b6 125static bfd_boolean
116c20d2
NC
126bfd_mach_o_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
127 asymbol *isymbol ATTRIBUTE_UNUSED,
128 bfd *obfd ATTRIBUTE_UNUSED,
129 asymbol *osymbol ATTRIBUTE_UNUSED)
3af9a47b 130{
b34976b6 131 return TRUE;
3af9a47b
NC
132}
133
134/* Copy any private info we understand from the input section
135 to the output section. */
136
b34976b6 137static bfd_boolean
116c20d2
NC
138bfd_mach_o_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
139 asection *isection ATTRIBUTE_UNUSED,
140 bfd *obfd ATTRIBUTE_UNUSED,
141 asection *osection ATTRIBUTE_UNUSED)
3af9a47b 142{
b34976b6 143 return TRUE;
3af9a47b
NC
144}
145
146/* Copy any private info we understand from the input bfd
147 to the output bfd. */
148
b34976b6 149static bfd_boolean
116c20d2 150bfd_mach_o_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
3af9a47b
NC
151{
152 BFD_ASSERT (bfd_mach_o_valid (ibfd));
153 BFD_ASSERT (bfd_mach_o_valid (obfd));
154
155 obfd->tdata.mach_o_data = ibfd->tdata.mach_o_data;
156 obfd->tdata.mach_o_data->ibfd = ibfd;
b34976b6 157 return TRUE;
3af9a47b
NC
158}
159
160static long
116c20d2 161bfd_mach_o_count_symbols (bfd *abfd)
3af9a47b
NC
162{
163 bfd_mach_o_data_struct *mdata = NULL;
164 long nsyms = 0;
165 unsigned long i;
a95a4550 166
3af9a47b
NC
167 BFD_ASSERT (bfd_mach_o_valid (abfd));
168 mdata = abfd->tdata.mach_o_data;
169
170 for (i = 0; i < mdata->header.ncmds; i++)
171 if (mdata->commands[i].type == BFD_MACH_O_LC_SYMTAB)
172 {
173 bfd_mach_o_symtab_command *sym = &mdata->commands[i].command.symtab;
174 nsyms += sym->nsyms;
175 }
176
177 return nsyms;
178}
179
180static long
116c20d2 181bfd_mach_o_get_symtab_upper_bound (bfd *abfd)
3af9a47b
NC
182{
183 long nsyms = bfd_mach_o_count_symbols (abfd);
184
185 if (nsyms < 0)
186 return nsyms;
187
188 return ((nsyms + 1) * sizeof (asymbol *));
189}
190
191static long
116c20d2 192bfd_mach_o_canonicalize_symtab (bfd *abfd, asymbol **alocation)
3af9a47b
NC
193{
194 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
195 long nsyms = bfd_mach_o_count_symbols (abfd);
196 asymbol **csym = alocation;
197 unsigned long i, j;
198
199 if (nsyms < 0)
200 return nsyms;
201
202 for (i = 0; i < mdata->header.ncmds; i++)
203 {
204 if (mdata->commands[i].type == BFD_MACH_O_LC_SYMTAB)
205 {
206 bfd_mach_o_symtab_command *sym = &mdata->commands[i].command.symtab;
207
208 if (bfd_mach_o_scan_read_symtab_symbols (abfd, &mdata->commands[i].command.symtab) != 0)
209 {
6cee3f79 210 fprintf (stderr, "bfd_mach_o_canonicalize_symtab: unable to load symbols for section %lu\n", i);
3af9a47b
NC
211 return 0;
212 }
213
214 BFD_ASSERT (sym->symbols != NULL);
215
216 for (j = 0; j < sym->nsyms; j++)
217 {
218 BFD_ASSERT (csym < (alocation + nsyms));
219 *csym++ = &sym->symbols[j];
220 }
221 }
222 }
223
224 *csym++ = NULL;
a95a4550 225
3af9a47b
NC
226 return nsyms;
227}
228
229static void
116c20d2
NC
230bfd_mach_o_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
231 asymbol *symbol,
232 symbol_info *ret)
3af9a47b
NC
233{
234 bfd_symbol_info (symbol, ret);
235}
236
237static void
116c20d2
NC
238bfd_mach_o_print_symbol (bfd *abfd,
239 PTR afile,
240 asymbol *symbol,
241 bfd_print_symbol_type how)
3af9a47b
NC
242{
243 FILE *file = (FILE *) afile;
244
245 switch (how)
246 {
247 case bfd_print_symbol_name:
248 fprintf (file, "%s", symbol->name);
249 break;
250 default:
251 bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
252 fprintf (file, " %-5s %s", symbol->section->name, symbol->name);
253 }
254}
255
256static void
116c20d2
NC
257bfd_mach_o_convert_architecture (bfd_mach_o_cpu_type mtype,
258 bfd_mach_o_cpu_subtype msubtype ATTRIBUTE_UNUSED,
259 enum bfd_architecture *type,
260 unsigned long *subtype)
3af9a47b
NC
261{
262 *subtype = bfd_arch_unknown;
263
264 switch (mtype)
265 {
266 case BFD_MACH_O_CPU_TYPE_VAX: *type = bfd_arch_vax; break;
267 case BFD_MACH_O_CPU_TYPE_MC680x0: *type = bfd_arch_m68k; break;
268 case BFD_MACH_O_CPU_TYPE_I386: *type = bfd_arch_i386; break;
269 case BFD_MACH_O_CPU_TYPE_MIPS: *type = bfd_arch_mips; break;
270 case BFD_MACH_O_CPU_TYPE_MC98000: *type = bfd_arch_m98k; break;
271 case BFD_MACH_O_CPU_TYPE_HPPA: *type = bfd_arch_hppa; break;
272 case BFD_MACH_O_CPU_TYPE_ARM: *type = bfd_arch_arm; break;
273 case BFD_MACH_O_CPU_TYPE_MC88000: *type = bfd_arch_m88k; break;
274 case BFD_MACH_O_CPU_TYPE_SPARC: *type = bfd_arch_sparc; break;
275 case BFD_MACH_O_CPU_TYPE_I860: *type = bfd_arch_i860; break;
276 case BFD_MACH_O_CPU_TYPE_ALPHA: *type = bfd_arch_alpha; break;
277 case BFD_MACH_O_CPU_TYPE_POWERPC: *type = bfd_arch_powerpc; break;
278 default: *type = bfd_arch_unknown; break;
279 }
280
281 switch (*type)
282 {
283 case bfd_arch_i386: *subtype = bfd_mach_i386_i386; break;
284 case bfd_arch_sparc: *subtype = bfd_mach_sparc; break;
285 default:
286 *subtype = bfd_arch_unknown;
287 }
288}
a95a4550 289
116c20d2
NC
290static int
291bfd_mach_o_write_header (bfd *abfd, bfd_mach_o_header *header)
292{
293 unsigned char buf[28];
294
295 bfd_h_put_32 (abfd, header->magic, buf + 0);
296 bfd_h_put_32 (abfd, header->cputype, buf + 4);
297 bfd_h_put_32 (abfd, header->cpusubtype, buf + 8);
298 bfd_h_put_32 (abfd, header->filetype, buf + 12);
299 bfd_h_put_32 (abfd, header->ncmds, buf + 16);
300 bfd_h_put_32 (abfd, header->sizeofcmds, buf + 20);
301 bfd_h_put_32 (abfd, header->flags, buf + 24);
302
303 bfd_seek (abfd, 0, SEEK_SET);
304 if (bfd_bwrite ((PTR) buf, 28, abfd) != 28)
305 return -1;
306
307 return 0;
308}
309
310static int
311bfd_mach_o_scan_write_thread (bfd *abfd,
312 bfd_mach_o_load_command *command)
313{
314 bfd_mach_o_thread_command *cmd = &command->command.thread;
315 unsigned int i;
316 unsigned char buf[8];
317 bfd_vma offset;
318 unsigned int nflavours;
319
320 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
321 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
322
323 offset = 8;
324 nflavours = 0;
325 for (i = 0; i < cmd->nflavours; i++)
326 {
327 BFD_ASSERT ((cmd->flavours[i].size % 4) == 0);
328 BFD_ASSERT (cmd->flavours[i].offset == (command->offset + offset + 8));
329
330 bfd_h_put_32 (abfd, cmd->flavours[i].flavour, buf);
331 bfd_h_put_32 (abfd, (cmd->flavours[i].size / 4), buf + 4);
332
333 bfd_seek (abfd, command->offset + offset, SEEK_SET);
334 if (bfd_bwrite ((PTR) buf, 8, abfd) != 8)
335 return -1;
336
337 offset += cmd->flavours[i].size + 8;
338 }
339
340 return 0;
341}
342
343static int
344bfd_mach_o_scan_write_section (bfd *abfd,
345 bfd_mach_o_section *section,
346 bfd_vma offset)
347{
348 unsigned char buf[68];
349
350 memcpy (buf, section->sectname, 16);
351 memcpy (buf + 16, section->segname, 16);
352 bfd_h_put_32 (abfd, section->addr, buf + 32);
353 bfd_h_put_32 (abfd, section->size, buf + 36);
354 bfd_h_put_32 (abfd, section->offset, buf + 40);
355 bfd_h_put_32 (abfd, section->align, buf + 44);
356 bfd_h_put_32 (abfd, section->reloff, buf + 48);
357 bfd_h_put_32 (abfd, section->nreloc, buf + 52);
358 bfd_h_put_32 (abfd, section->flags, buf + 56);
359 /* bfd_h_put_32 (abfd, section->reserved1, buf + 60); */
360 /* bfd_h_put_32 (abfd, section->reserved2, buf + 64); */
361
362 bfd_seek (abfd, offset, SEEK_SET);
363 if (bfd_bwrite ((PTR) buf, 68, abfd) != 68)
364 return -1;
365
366 return 0;
367}
368
369static int
370bfd_mach_o_scan_write_segment (bfd *abfd, bfd_mach_o_load_command *command)
371{
372 unsigned char buf[48];
373 bfd_mach_o_segment_command *seg = &command->command.segment;
374 unsigned long i;
375
376 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
377
378 memcpy (buf, seg->segname, 16);
379 bfd_h_put_32 (abfd, seg->vmaddr, buf + 16);
380 bfd_h_put_32 (abfd, seg->vmsize, buf + 20);
381 bfd_h_put_32 (abfd, seg->fileoff, buf + 24);
382 bfd_h_put_32 (abfd, seg->filesize, buf + 28);
383 bfd_h_put_32 (abfd, 0 /* seg->maxprot */, buf + 32);
384 bfd_h_put_32 (abfd, 0 /* seg->initprot */, buf + 36);
385 bfd_h_put_32 (abfd, seg->nsects, buf + 40);
386 bfd_h_put_32 (abfd, seg->flags, buf + 44);
387
388 bfd_seek (abfd, command->offset + 8, SEEK_SET);
389 if (bfd_bwrite ((PTR) buf, 48, abfd) != 48)
390 return -1;
391
392 {
393 char buf[1024];
394 bfd_vma nbytes = seg->filesize;
395 bfd_vma curoff = seg->fileoff;
396
397 while (nbytes > 0)
398 {
399 bfd_vma thisread = nbytes;
400
401 if (thisread > 1024)
402 thisread = 1024;
403
404 bfd_seek (abfd, curoff, SEEK_SET);
405 if (bfd_bread ((PTR) buf, thisread, abfd) != thisread)
406 return -1;
407
408 bfd_seek (abfd, curoff, SEEK_SET);
409 if (bfd_bwrite ((PTR) buf, thisread, abfd) != thisread)
410 return -1;
411
412 nbytes -= thisread;
413 curoff += thisread;
414 }
415 }
416
417 for (i = 0; i < seg->nsects; i++)
418 {
419 bfd_vma segoff = command->offset + 48 + 8 + (i * 68);
420
421 if (bfd_mach_o_scan_write_section (abfd, &seg->sections[i], segoff) != 0)
422 return -1;
423 }
424
425 return 0;
426}
427
428static int
429bfd_mach_o_scan_write_symtab_symbols (bfd *abfd,
430 bfd_mach_o_load_command *command)
431{
432 bfd_mach_o_symtab_command *sym = &command->command.symtab;
433 asymbol *s = NULL;
434 unsigned long i;
435
436 for (i = 0; i < sym->nsyms; i++)
437 {
438 unsigned char buf[12];
439 bfd_vma symoff = sym->symoff + (i * 12);
440 unsigned char ntype = 0;
441 unsigned char nsect = 0;
442 short ndesc = 0;
443
444 s = &sym->symbols[i];
445
446 /* Instead just set from the stored values. */
447 ntype = (s->udata.i >> 24) & 0xff;
448 nsect = (s->udata.i >> 16) & 0xff;
449 ndesc = s->udata.i & 0xffff;
450
451 bfd_h_put_32 (abfd, s->name - sym->strtab, buf);
452 bfd_h_put_8 (abfd, ntype, buf + 4);
453 bfd_h_put_8 (abfd, nsect, buf + 5);
454 bfd_h_put_16 (abfd, ndesc, buf + 6);
455 bfd_h_put_32 (abfd, s->section->vma + s->value, buf + 8);
456
457 bfd_seek (abfd, symoff, SEEK_SET);
458 if (bfd_bwrite ((PTR) buf, 12, abfd) != 12)
459 {
460 fprintf (stderr, "bfd_mach_o_scan_write_symtab_symbols: unable to write %d bytes at %lu\n",
461 12, (unsigned long) symoff);
462 return -1;
463 }
464 }
465
466 return 0;
467}
468
469static int
470bfd_mach_o_scan_write_symtab (bfd *abfd, bfd_mach_o_load_command *command)
471{
472 bfd_mach_o_symtab_command *seg = &command->command.symtab;
473 unsigned char buf[16];
474
475 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
476
477 bfd_h_put_32 (abfd, seg->symoff, buf);
478 bfd_h_put_32 (abfd, seg->nsyms, buf + 4);
479 bfd_h_put_32 (abfd, seg->stroff, buf + 8);
480 bfd_h_put_32 (abfd, seg->strsize, buf + 12);
481
482 bfd_seek (abfd, command->offset + 8, SEEK_SET);
483 if (bfd_bwrite ((PTR) buf, 16, abfd) != 16)
484 return -1;
485
486 if (bfd_mach_o_scan_write_symtab_symbols (abfd, command) != 0)
487 return -1;
488
489 return 0;
490}
491
b34976b6 492static bfd_boolean
116c20d2 493bfd_mach_o_write_contents (bfd *abfd)
3af9a47b
NC
494{
495 unsigned int i;
496 asection *s;
497
498 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
499
500 /* Write data sections first in case they overlap header data to be
501 written later. */
502
503 for (s = abfd->sections; s != (asection *) NULL; s = s->next)
504 ;
505
3af9a47b
NC
506 /* Now write header information. */
507 if (bfd_mach_o_write_header (abfd, &mdata->header) != 0)
b34976b6 508 return FALSE;
3af9a47b
NC
509
510 for (i = 0; i < mdata->header.ncmds; i++)
511 {
512 unsigned char buf[8];
513 bfd_mach_o_load_command *cur = &mdata->commands[i];
514 unsigned long typeflag;
515
516 typeflag = cur->type_required ? cur->type & BFD_MACH_O_LC_REQ_DYLD : cur->type;
517
518 bfd_h_put_32 (abfd, typeflag, buf);
519 bfd_h_put_32 (abfd, cur->len, buf + 4);
520
521 bfd_seek (abfd, cur->offset, SEEK_SET);
522 if (bfd_bwrite ((PTR) buf, 8, abfd) != 8)
b34976b6 523 return FALSE;
3af9a47b
NC
524
525 switch (cur->type)
526 {
527 case BFD_MACH_O_LC_SEGMENT:
528 if (bfd_mach_o_scan_write_segment (abfd, cur) != 0)
b34976b6 529 return FALSE;
3af9a47b
NC
530 break;
531 case BFD_MACH_O_LC_SYMTAB:
532 if (bfd_mach_o_scan_write_symtab (abfd, cur) != 0)
b34976b6 533 return FALSE;
3af9a47b
NC
534 break;
535 case BFD_MACH_O_LC_SYMSEG:
536 break;
537 case BFD_MACH_O_LC_THREAD:
538 case BFD_MACH_O_LC_UNIXTHREAD:
539 if (bfd_mach_o_scan_write_thread (abfd, cur) != 0)
b34976b6 540 return FALSE;
3af9a47b
NC
541 break;
542 case BFD_MACH_O_LC_LOADFVMLIB:
543 case BFD_MACH_O_LC_IDFVMLIB:
544 case BFD_MACH_O_LC_IDENT:
545 case BFD_MACH_O_LC_FVMFILE:
546 case BFD_MACH_O_LC_PREPAGE:
547 case BFD_MACH_O_LC_DYSYMTAB:
548 case BFD_MACH_O_LC_LOAD_DYLIB:
549 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
550 case BFD_MACH_O_LC_ID_DYLIB:
551 case BFD_MACH_O_LC_LOAD_DYLINKER:
552 case BFD_MACH_O_LC_ID_DYLINKER:
553 case BFD_MACH_O_LC_PREBOUND_DYLIB:
554 case BFD_MACH_O_LC_ROUTINES:
555 case BFD_MACH_O_LC_SUB_FRAMEWORK:
556 break;
557 default:
558 fprintf (stderr,
559 "unable to write unknown load command 0x%lx\n",
560 (long) cur->type);
b34976b6 561 return FALSE;
3af9a47b
NC
562 }
563 }
564
b34976b6 565 return TRUE;
3af9a47b
NC
566}
567
568static int
116c20d2
NC
569bfd_mach_o_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
570 bfd_boolean b ATTRIBUTE_UNUSED)
3af9a47b
NC
571{
572 return 0;
573}
574
575/* Make an empty symbol. This is required only because
576 bfd_make_section_anyway wants to create a symbol for the section. */
577
578static asymbol *
116c20d2 579bfd_mach_o_make_empty_symbol (bfd *abfd)
3af9a47b
NC
580{
581 asymbol *new;
582
116c20d2 583 new = bfd_zalloc (abfd, sizeof (* new));
3af9a47b
NC
584 if (new == NULL)
585 return new;
586 new->the_bfd = abfd;
587 return new;
588}
589
590static int
116c20d2 591bfd_mach_o_read_header (bfd *abfd, bfd_mach_o_header *header)
3af9a47b
NC
592{
593 unsigned char buf[28];
edeb6e24 594 bfd_vma (*get32) (const void *) = NULL;
3af9a47b
NC
595
596 bfd_seek (abfd, 0, SEEK_SET);
597
598 if (bfd_bread ((PTR) buf, 28, abfd) != 28)
599 return -1;
600
601 if (bfd_getb32 (buf) == 0xfeedface)
602 {
603 header->byteorder = BFD_ENDIAN_BIG;
604 header->magic = 0xfeedface;
605 get32 = bfd_getb32;
606 }
607 else if (bfd_getl32 (buf) == 0xfeedface)
608 {
a95a4550 609 header->byteorder = BFD_ENDIAN_LITTLE;
3af9a47b
NC
610 header->magic = 0xfeedface;
611 get32 = bfd_getl32;
612 }
613 else
614 {
615 header->byteorder = BFD_ENDIAN_UNKNOWN;
616 return -1;
617 }
a95a4550 618
3af9a47b
NC
619 header->cputype = (*get32) (buf + 4);
620 header->cpusubtype = (*get32) (buf + 8);
621 header->filetype = (*get32) (buf + 12);
622 header->ncmds = (*get32) (buf + 16);
623 header->sizeofcmds = (*get32) (buf + 20);
624 header->flags = (*get32) (buf + 24);
625
626 return 0;
627}
628
629static asection *
116c20d2 630bfd_mach_o_make_bfd_section (bfd *abfd, bfd_mach_o_section *section)
3af9a47b
NC
631{
632 asection *bfdsec;
633 char *sname;
634 const char *prefix = "LC_SEGMENT";
635 unsigned int snamelen;
636
637 snamelen = strlen (prefix) + 1
638 + strlen (section->segname) + 1
639 + strlen (section->sectname) + 1;
640
116c20d2 641 sname = bfd_alloc (abfd, snamelen);
3af9a47b
NC
642 if (sname == NULL)
643 return NULL;
644 sprintf (sname, "%s.%s.%s", prefix, section->segname, section->sectname);
645
646 bfdsec = bfd_make_section_anyway (abfd, sname);
647 if (bfdsec == NULL)
648 return NULL;
a95a4550 649
3af9a47b
NC
650 bfdsec->vma = section->addr;
651 bfdsec->lma = section->addr;
eea6121a 652 bfdsec->size = section->size;
3af9a47b
NC
653 bfdsec->filepos = section->offset;
654 bfdsec->alignment_power = section->align;
655
656 if (section->flags & BFD_MACH_O_S_ZEROFILL)
657 bfdsec->flags = SEC_ALLOC;
658 else
659 bfdsec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE;
660
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
968 bfdsec = bfd_make_section_anyway (abfd, sname);
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;
977 bfdsec->flags = SEC_HAS_CONTENTS;
978
979 cmd->section = bfdsec;
980
981 return 0;
982}
983
984static int
116c20d2 985bfd_mach_o_scan_read_dylib (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
986{
987 bfd_mach_o_dylib_command *cmd = &command->command.dylib;
988 unsigned char buf[16];
989 unsigned int nameoff;
990 asection *bfdsec;
991 char *sname;
992 const char *prefix;
993
994 BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLIB)
995 || (command->type == BFD_MACH_O_LC_LOAD_DYLIB)
996 || (command->type == BFD_MACH_O_LC_LOAD_WEAK_DYLIB));
997
998 bfd_seek (abfd, command->offset + 8, SEEK_SET);
999 if (bfd_bread ((PTR) buf, 16, abfd) != 16)
1000 return -1;
1001
1002 nameoff = bfd_h_get_32 (abfd, buf + 0);
1003 cmd->timestamp = bfd_h_get_32 (abfd, buf + 4);
1004 cmd->current_version = bfd_h_get_32 (abfd, buf + 8);
1005 cmd->compatibility_version = bfd_h_get_32 (abfd, buf + 12);
1006
1007 cmd->name_offset = command->offset + nameoff;
1008 cmd->name_len = command->len - nameoff;
1009
1010 if (command->type == BFD_MACH_O_LC_LOAD_DYLIB)
1011 prefix = "LC_LOAD_DYLIB";
1012 else if (command->type == BFD_MACH_O_LC_LOAD_WEAK_DYLIB)
1013 prefix = "LC_LOAD_WEAK_DYLIB";
1014 else if (command->type == BFD_MACH_O_LC_ID_DYLIB)
1015 prefix = "LC_ID_DYLIB";
1016 else
1017 abort ();
1018
116c20d2 1019 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
1020 if (sname == NULL)
1021 return -1;
1022 strcpy (sname, prefix);
1023
1024 bfdsec = bfd_make_section_anyway (abfd, sname);
1025 if (bfdsec == NULL)
1026 return -1;
a95a4550 1027
3af9a47b
NC
1028 bfdsec->vma = 0;
1029 bfdsec->lma = 0;
eea6121a 1030 bfdsec->size = command->len - 8;
3af9a47b
NC
1031 bfdsec->filepos = command->offset + 8;
1032 bfdsec->alignment_power = 0;
1033 bfdsec->flags = SEC_HAS_CONTENTS;
1034
1035 cmd->section = bfdsec;
1036
1037 return 0;
1038}
1039
1040static int
116c20d2
NC
1041bfd_mach_o_scan_read_prebound_dylib (bfd *abfd ATTRIBUTE_UNUSED,
1042 bfd_mach_o_load_command *command ATTRIBUTE_UNUSED)
3af9a47b
NC
1043{
1044 /* bfd_mach_o_prebound_dylib_command *cmd = &command->command.prebound_dylib; */
1045
1046 BFD_ASSERT (command->type == BFD_MACH_O_LC_PREBOUND_DYLIB);
1047 return 0;
1048}
1049
1050static int
116c20d2 1051bfd_mach_o_scan_read_thread (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1052{
1053 bfd_mach_o_data_struct *mdata = NULL;
1054 bfd_mach_o_thread_command *cmd = &command->command.thread;
1055 unsigned char buf[8];
1056 bfd_vma offset;
1057 unsigned int nflavours;
1058 unsigned int i;
1059
1060 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
1061 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
1062
1063 BFD_ASSERT (bfd_mach_o_valid (abfd));
1064 mdata = abfd->tdata.mach_o_data;
a95a4550 1065
3af9a47b
NC
1066 offset = 8;
1067 nflavours = 0;
1068 while (offset != command->len)
1069 {
1070 if (offset >= command->len)
1071 return -1;
1072
1073 bfd_seek (abfd, command->offset + offset, SEEK_SET);
1074
1075 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
1076 return -1;
1077
1078 offset += 8 + bfd_h_get_32 (abfd, buf + 4) * 4;
1079 nflavours++;
1080 }
1081
116c20d2 1082 cmd->flavours = bfd_alloc (abfd, nflavours * sizeof (bfd_mach_o_thread_flavour));
3af9a47b
NC
1083 if (cmd->flavours == NULL)
1084 return -1;
1085 cmd->nflavours = nflavours;
1086
1087 offset = 8;
1088 nflavours = 0;
1089 while (offset != command->len)
1090 {
1091 if (offset >= command->len)
1092 return -1;
1093
1094 if (nflavours >= cmd->nflavours)
1095 return -1;
1096
1097 bfd_seek (abfd, command->offset + offset, SEEK_SET);
1098
1099 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
1100 return -1;
1101
1102 cmd->flavours[nflavours].flavour = bfd_h_get_32 (abfd, buf);
1103 cmd->flavours[nflavours].offset = command->offset + offset + 8;
1104 cmd->flavours[nflavours].size = bfd_h_get_32 (abfd, buf + 4) * 4;
1105 offset += cmd->flavours[nflavours].size + 8;
1106 nflavours++;
1107 }
1108
1109 for (i = 0; i < nflavours; i++)
1110 {
1111 asection *bfdsec;
1112 unsigned int snamelen;
1113 char *sname;
1114 const char *flavourstr;
1115 const char *prefix = "LC_THREAD";
a95a4550
AM
1116 unsigned int j = 0;
1117
3af9a47b
NC
1118 switch (mdata->header.cputype)
1119 {
1120 case BFD_MACH_O_CPU_TYPE_POWERPC:
1121 flavourstr = bfd_mach_o_ppc_flavour_string (cmd->flavours[i].flavour);
1122 break;
1123 case BFD_MACH_O_CPU_TYPE_I386:
1124 flavourstr = bfd_mach_o_i386_flavour_string (cmd->flavours[i].flavour);
1125 break;
1126 default:
1127 flavourstr = "UNKNOWN_ARCHITECTURE";
1128 break;
1129 }
a95a4550 1130
3af9a47b 1131 snamelen = strlen (prefix) + 1 + 20 + 1 + strlen (flavourstr) + 1;
116c20d2 1132 sname = bfd_alloc (abfd, snamelen);
3af9a47b
NC
1133 if (sname == NULL)
1134 return -1;
1135
1136 for (;;)
1137 {
a95a4550
AM
1138 sprintf (sname, "%s.%s.%u", prefix, flavourstr, j);
1139 if (bfd_get_section_by_name (abfd, sname) == NULL)
3af9a47b 1140 break;
a95a4550 1141 j++;
3af9a47b
NC
1142 }
1143
1144 bfdsec = bfd_make_section (abfd, sname);
a95a4550 1145
3af9a47b
NC
1146 bfdsec->vma = 0;
1147 bfdsec->lma = 0;
eea6121a 1148 bfdsec->size = cmd->flavours[i].size;
3af9a47b
NC
1149 bfdsec->filepos = cmd->flavours[i].offset;
1150 bfdsec->alignment_power = 0x0;
1151 bfdsec->flags = SEC_HAS_CONTENTS;
1152
1153 cmd->section = bfdsec;
1154 }
1155
1156 return 0;
1157}
1158
a95a4550 1159static int
116c20d2 1160bfd_mach_o_scan_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1161{
1162 bfd_mach_o_dysymtab_command *seg = &command->command.dysymtab;
1163 unsigned char buf[72];
1164
1165 BFD_ASSERT (command->type == BFD_MACH_O_LC_DYSYMTAB);
1166
1167 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1168 if (bfd_bread ((PTR) buf, 72, abfd) != 72)
1169 return -1;
1170
1171 seg->ilocalsym = bfd_h_get_32 (abfd, buf + 0);
1172 seg->nlocalsym = bfd_h_get_32 (abfd, buf + 4);
1173 seg->iextdefsym = bfd_h_get_32 (abfd, buf + 8);
1174 seg->nextdefsym = bfd_h_get_32 (abfd, buf + 12);
1175 seg->iundefsym = bfd_h_get_32 (abfd, buf + 16);
1176 seg->nundefsym = bfd_h_get_32 (abfd, buf + 20);
1177 seg->tocoff = bfd_h_get_32 (abfd, buf + 24);
1178 seg->ntoc = bfd_h_get_32 (abfd, buf + 28);
1179 seg->modtaboff = bfd_h_get_32 (abfd, buf + 32);
1180 seg->nmodtab = bfd_h_get_32 (abfd, buf + 36);
1181 seg->extrefsymoff = bfd_h_get_32 (abfd, buf + 40);
1182 seg->nextrefsyms = bfd_h_get_32 (abfd, buf + 44);
1183 seg->indirectsymoff = bfd_h_get_32 (abfd, buf + 48);
1184 seg->nindirectsyms = bfd_h_get_32 (abfd, buf + 52);
1185 seg->extreloff = bfd_h_get_32 (abfd, buf + 56);
1186 seg->nextrel = bfd_h_get_32 (abfd, buf + 60);
1187 seg->locreloff = bfd_h_get_32 (abfd, buf + 64);
1188 seg->nlocrel = bfd_h_get_32 (abfd, buf + 68);
1189
1190 return 0;
1191}
1192
a95a4550 1193static int
116c20d2 1194bfd_mach_o_scan_read_symtab (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1195{
1196 bfd_mach_o_symtab_command *seg = &command->command.symtab;
1197 unsigned char buf[16];
1198 asection *bfdsec;
1199 char *sname;
1200 const char *prefix = "LC_SYMTAB.stabs";
1201
1202 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
1203
1204 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1205 if (bfd_bread ((PTR) buf, 16, abfd) != 16)
1206 return -1;
a95a4550 1207
3af9a47b
NC
1208 seg->symoff = bfd_h_get_32 (abfd, buf);
1209 seg->nsyms = bfd_h_get_32 (abfd, buf + 4);
1210 seg->stroff = bfd_h_get_32 (abfd, buf + 8);
1211 seg->strsize = bfd_h_get_32 (abfd, buf + 12);
1212 seg->symbols = NULL;
1213 seg->strtab = NULL;
1214
116c20d2 1215 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
1216 if (sname == NULL)
1217 return -1;
1218 strcpy (sname, prefix);
1219
1220 bfdsec = bfd_make_section_anyway (abfd, sname);
1221 if (bfdsec == NULL)
1222 return -1;
a95a4550 1223
3af9a47b
NC
1224 bfdsec->vma = 0;
1225 bfdsec->lma = 0;
eea6121a 1226 bfdsec->size = seg->nsyms * 12;
3af9a47b
NC
1227 bfdsec->filepos = seg->symoff;
1228 bfdsec->alignment_power = 0;
1229 bfdsec->flags = SEC_HAS_CONTENTS;
1230
1231 seg->stabs_segment = bfdsec;
1232
1233 prefix = "LC_SYMTAB.stabstr";
116c20d2 1234 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
1235 if (sname == NULL)
1236 return -1;
1237 strcpy (sname, prefix);
1238
1239 bfdsec = bfd_make_section_anyway (abfd, sname);
1240 if (bfdsec == NULL)
1241 return -1;
a95a4550 1242
3af9a47b
NC
1243 bfdsec->vma = 0;
1244 bfdsec->lma = 0;
eea6121a 1245 bfdsec->size = seg->strsize;
3af9a47b
NC
1246 bfdsec->filepos = seg->stroff;
1247 bfdsec->alignment_power = 0;
1248 bfdsec->flags = SEC_HAS_CONTENTS;
1249
1250 seg->stabstr_segment = bfdsec;
1251
1252 return 0;
1253}
1254
1255static int
116c20d2 1256bfd_mach_o_scan_read_segment (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1257{
1258 unsigned char buf[48];
1259 bfd_mach_o_segment_command *seg = &command->command.segment;
1260 unsigned long i;
1261 asection *bfdsec;
1262 char *sname;
1263 const char *prefix = "LC_SEGMENT";
1264 unsigned int snamelen;
a95a4550 1265
3af9a47b
NC
1266 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
1267
1268 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1269 if (bfd_bread ((PTR) buf, 48, abfd) != 48)
1270 return -1;
1271
1272 memcpy (seg->segname, buf, 16);
1273 seg->vmaddr = bfd_h_get_32 (abfd, buf + 16);
1274 seg->vmsize = bfd_h_get_32 (abfd, buf + 20);
1275 seg->fileoff = bfd_h_get_32 (abfd, buf + 24);
1276 seg->filesize = bfd_h_get_32 (abfd, buf + 28);
1277 /* seg->maxprot = bfd_h_get_32 (abfd, buf + 32); */
1278 /* seg->initprot = bfd_h_get_32 (abfd, buf + 36); */
1279 seg->nsects = bfd_h_get_32 (abfd, buf + 40);
1280 seg->flags = bfd_h_get_32 (abfd, buf + 44);
1281
1282 snamelen = strlen (prefix) + 1 + strlen (seg->segname) + 1;
116c20d2 1283 sname = bfd_alloc (abfd, snamelen);
3af9a47b
NC
1284 if (sname == NULL)
1285 return -1;
1286 sprintf (sname, "%s.%s", prefix, seg->segname);
1287
1288 bfdsec = bfd_make_section_anyway (abfd, sname);
1289 if (bfdsec == NULL)
1290 return -1;
1291
1292 bfdsec->vma = seg->vmaddr;
1293 bfdsec->lma = seg->vmaddr;
eea6121a 1294 bfdsec->size = seg->filesize;
3af9a47b
NC
1295 bfdsec->filepos = seg->fileoff;
1296 bfdsec->alignment_power = 0x0;
1297 bfdsec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE;
1298
1299 seg->segment = bfdsec;
1300
1301 if (seg->nsects != 0)
1302 {
116c20d2 1303 seg->sections = bfd_alloc (abfd, seg->nsects * sizeof (bfd_mach_o_section));
3af9a47b
NC
1304 if (seg->sections == NULL)
1305 return -1;
a95a4550 1306
3af9a47b
NC
1307 for (i = 0; i < seg->nsects; i++)
1308 {
1309 bfd_vma segoff = command->offset + 48 + 8 + (i * 68);
1310
e84d6fca
AM
1311 if (bfd_mach_o_scan_read_section (abfd, &seg->sections[i],
1312 segoff) != 0)
3af9a47b 1313 return -1;
a95a4550 1314 }
3af9a47b
NC
1315 }
1316
1317 return 0;
1318}
1319
1320static int
116c20d2 1321bfd_mach_o_scan_read_command (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1322{
1323 unsigned char buf[8];
1324
1325 bfd_seek (abfd, command->offset, SEEK_SET);
1326 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
1327 return -1;
1328
1329 command->type = (bfd_h_get_32 (abfd, buf) & ~BFD_MACH_O_LC_REQ_DYLD);
e84d6fca
AM
1330 command->type_required = (bfd_h_get_32 (abfd, buf) & BFD_MACH_O_LC_REQ_DYLD
1331 ? 1 : 0);
3af9a47b
NC
1332 command->len = bfd_h_get_32 (abfd, buf + 4);
1333
1334 switch (command->type)
1335 {
1336 case BFD_MACH_O_LC_SEGMENT:
1337 if (bfd_mach_o_scan_read_segment (abfd, command) != 0)
1338 return -1;
1339 break;
1340 case BFD_MACH_O_LC_SYMTAB:
1341 if (bfd_mach_o_scan_read_symtab (abfd, command) != 0)
1342 return -1;
1343 break;
1344 case BFD_MACH_O_LC_SYMSEG:
1345 break;
1346 case BFD_MACH_O_LC_THREAD:
1347 case BFD_MACH_O_LC_UNIXTHREAD:
1348 if (bfd_mach_o_scan_read_thread (abfd, command) != 0)
1349 return -1;
1350 break;
1351 case BFD_MACH_O_LC_LOAD_DYLINKER:
1352 case BFD_MACH_O_LC_ID_DYLINKER:
1353 if (bfd_mach_o_scan_read_dylinker (abfd, command) != 0)
1354 return -1;
1355 break;
1356 case BFD_MACH_O_LC_LOAD_DYLIB:
1357 case BFD_MACH_O_LC_ID_DYLIB:
1358 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
1359 if (bfd_mach_o_scan_read_dylib (abfd, command) != 0)
1360 return -1;
1361 break;
1362 case BFD_MACH_O_LC_PREBOUND_DYLIB:
1363 if (bfd_mach_o_scan_read_prebound_dylib (abfd, command) != 0)
1364 return -1;
1365 break;
1366 case BFD_MACH_O_LC_LOADFVMLIB:
1367 case BFD_MACH_O_LC_IDFVMLIB:
1368 case BFD_MACH_O_LC_IDENT:
1369 case BFD_MACH_O_LC_FVMFILE:
1370 case BFD_MACH_O_LC_PREPAGE:
1371 case BFD_MACH_O_LC_ROUTINES:
1372 case BFD_MACH_O_LC_SUB_FRAMEWORK:
1373 break;
1374 case BFD_MACH_O_LC_DYSYMTAB:
1375 if (bfd_mach_o_scan_read_dysymtab (abfd, command) != 0)
1376 return -1;
1377 break;
1378 case BFD_MACH_O_LC_SUB_UMBRELLA:
1379 case BFD_MACH_O_LC_SUB_CLIENT:
1380 case BFD_MACH_O_LC_SUB_LIBRARY:
1381 case BFD_MACH_O_LC_TWOLEVEL_HINTS:
1382 case BFD_MACH_O_LC_PREBIND_CKSUM:
1383 break;
1384 default:
1385 fprintf (stderr, "unable to read unknown load command 0x%lx\n",
1386 (unsigned long) command->type);
1387 break;
1388 }
1389
1390 return 0;
1391}
1392
1393static void
116c20d2 1394bfd_mach_o_flatten_sections (bfd *abfd)
3af9a47b
NC
1395{
1396 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
1397 long csect = 0;
1398 unsigned long i, j;
a95a4550 1399
3af9a47b
NC
1400 mdata->nsects = 0;
1401
1402 for (i = 0; i < mdata->header.ncmds; i++)
1403 {
1404 if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT)
1405 {
e84d6fca
AM
1406 bfd_mach_o_segment_command *seg;
1407
1408 seg = &mdata->commands[i].command.segment;
3af9a47b
NC
1409 mdata->nsects += seg->nsects;
1410 }
1411 }
1412
e84d6fca
AM
1413 mdata->sections = bfd_alloc (abfd,
1414 mdata->nsects * sizeof (bfd_mach_o_section *));
3af9a47b
NC
1415 csect = 0;
1416
1417 for (i = 0; i < mdata->header.ncmds; i++)
1418 {
1419 if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT)
1420 {
e84d6fca 1421 bfd_mach_o_segment_command *seg;
3af9a47b 1422
e84d6fca 1423 seg = &mdata->commands[i].command.segment;
3af9a47b
NC
1424 BFD_ASSERT (csect + seg->nsects <= mdata->nsects);
1425
1426 for (j = 0; j < seg->nsects; j++)
1427 mdata->sections[csect++] = &seg->sections[j];
1428 }
1429 }
1430}
1431
1432int
116c20d2 1433bfd_mach_o_scan_start_address (bfd *abfd)
3af9a47b
NC
1434{
1435 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
1436 bfd_mach_o_thread_command *cmd = NULL;
1437 unsigned long i;
1438
1439 for (i = 0; i < mdata->header.ncmds; i++)
1440 {
1441 if ((mdata->commands[i].type == BFD_MACH_O_LC_THREAD) ||
1442 (mdata->commands[i].type == BFD_MACH_O_LC_UNIXTHREAD))
1443 {
1444 if (cmd == NULL)
1445 cmd = &mdata->commands[i].command.thread;
1446 else
1447 return 0;
1448 }
1449 }
1450
1451 if (cmd == NULL)
1452 return 0;
1453
1454 for (i = 0; i < cmd->nflavours; i++)
1455 {
a95a4550 1456 if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_I386)
e84d6fca
AM
1457 && (cmd->flavours[i].flavour
1458 == (unsigned long) BFD_MACH_O_i386_THREAD_STATE))
3af9a47b
NC
1459 {
1460 unsigned char buf[4];
1461
1462 bfd_seek (abfd, cmd->flavours[i].offset + 40, SEEK_SET);
1463
1464 if (bfd_bread (buf, 4, abfd) != 4)
1465 return -1;
1466
1467 abfd->start_address = bfd_h_get_32 (abfd, buf);
1468 }
a95a4550 1469 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC)
3af9a47b
NC
1470 && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE))
1471 {
1472 unsigned char buf[4];
1473
1474 bfd_seek (abfd, cmd->flavours[i].offset + 0, SEEK_SET);
1475
1476 if (bfd_bread (buf, 4, abfd) != 4)
1477 return -1;
1478
1479 abfd->start_address = bfd_h_get_32 (abfd, buf);
1480 }
1481 }
1482
1483 return 0;
1484}
1485
1486int
116c20d2
NC
1487bfd_mach_o_scan (bfd *abfd,
1488 bfd_mach_o_header *header,
1489 bfd_mach_o_data_struct *mdata)
3af9a47b
NC
1490{
1491 unsigned int i;
3af9a47b
NC
1492 enum bfd_architecture cputype;
1493 unsigned long cpusubtype;
1494
3af9a47b
NC
1495 mdata->header = *header;
1496 mdata->symbols = NULL;
1497
e84d6fca
AM
1498 abfd->flags = (abfd->xvec->object_flags
1499 | (abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS)));
3af9a47b
NC
1500 abfd->tdata.mach_o_data = mdata;
1501
e84d6fca
AM
1502 bfd_mach_o_convert_architecture (header->cputype, header->cpusubtype,
1503 &cputype, &cpusubtype);
3af9a47b
NC
1504 if (cputype == bfd_arch_unknown)
1505 {
1506 fprintf (stderr, "bfd_mach_o_scan: unknown architecture 0x%lx/0x%lx\n",
1507 header->cputype, header->cpusubtype);
1508 return -1;
1509 }
1510
1511 bfd_set_arch_mach (abfd, cputype, cpusubtype);
a95a4550 1512
3af9a47b
NC
1513 if (header->ncmds != 0)
1514 {
116c20d2 1515 mdata->commands = bfd_alloc (abfd, header->ncmds * sizeof (bfd_mach_o_load_command));
3af9a47b
NC
1516 if (mdata->commands == NULL)
1517 return -1;
a95a4550 1518
3af9a47b
NC
1519 for (i = 0; i < header->ncmds; i++)
1520 {
1521 bfd_mach_o_load_command *cur = &mdata->commands[i];
1522
1523 if (i == 0)
1524 cur->offset = 28;
1525 else
1526 {
1527 bfd_mach_o_load_command *prev = &mdata->commands[i - 1];
1528 cur->offset = prev->offset + prev->len;
1529 }
1530
1531 if (bfd_mach_o_scan_read_command (abfd, cur) < 0)
1532 return -1;
a95a4550 1533 }
3af9a47b
NC
1534 }
1535
1536 if (bfd_mach_o_scan_start_address (abfd) < 0)
7e3102a7 1537 return -1;
3af9a47b
NC
1538
1539 bfd_mach_o_flatten_sections (abfd);
3af9a47b
NC
1540 return 0;
1541}
1542
b34976b6 1543bfd_boolean
116c20d2 1544bfd_mach_o_mkobject (bfd *abfd)
3af9a47b
NC
1545{
1546 bfd_mach_o_data_struct *mdata = NULL;
1547
116c20d2 1548 mdata = bfd_alloc (abfd, sizeof (bfd_mach_o_data_struct));
3af9a47b 1549 if (mdata == NULL)
b34976b6 1550 return FALSE;
3af9a47b
NC
1551 abfd->tdata.mach_o_data = mdata;
1552
1553 mdata->header.magic = 0;
1554 mdata->header.cputype = 0;
1555 mdata->header.cpusubtype = 0;
1556 mdata->header.filetype = 0;
1557 mdata->header.ncmds = 0;
1558 mdata->header.sizeofcmds = 0;
1559 mdata->header.flags = 0;
1560 mdata->header.byteorder = BFD_ENDIAN_UNKNOWN;
1561 mdata->commands = NULL;
1562 mdata->nsymbols = 0;
1563 mdata->symbols = NULL;
1564 mdata->nsects = 0;
1565 mdata->sections = NULL;
1566 mdata->ibfd = NULL;
1567
b34976b6 1568 return TRUE;
3af9a47b
NC
1569}
1570
1571const bfd_target *
116c20d2 1572bfd_mach_o_object_p (bfd *abfd)
3af9a47b 1573{
e84d6fca 1574 struct bfd_preserve preserve;
3af9a47b
NC
1575 bfd_mach_o_header header;
1576
e84d6fca 1577 preserve.marker = NULL;
3af9a47b 1578 if (bfd_mach_o_read_header (abfd, &header) != 0)
e84d6fca 1579 goto wrong;
3af9a47b 1580
e84d6fca
AM
1581 if (! (header.byteorder == BFD_ENDIAN_BIG
1582 || header.byteorder == BFD_ENDIAN_LITTLE))
3af9a47b 1583 {
e84d6fca
AM
1584 fprintf (stderr, "unknown header byte-order value 0x%lx\n",
1585 (long) header.byteorder);
1586 goto wrong;
3af9a47b
NC
1587 }
1588
e84d6fca
AM
1589 if (! ((header.byteorder == BFD_ENDIAN_BIG
1590 && abfd->xvec->byteorder == BFD_ENDIAN_BIG
1591 && abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
1592 || (header.byteorder == BFD_ENDIAN_LITTLE
1593 && abfd->xvec->byteorder == BFD_ENDIAN_LITTLE
1594 && abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)))
1595 goto wrong;
3af9a47b 1596
e84d6fca
AM
1597 preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct));
1598 if (preserve.marker == NULL
1599 || !bfd_preserve_save (abfd, &preserve))
1600 goto fail;
3af9a47b 1601
e84d6fca
AM
1602 if (bfd_mach_o_scan (abfd, &header,
1603 (bfd_mach_o_data_struct *) preserve.marker) != 0)
1604 goto wrong;
a95a4550 1605
e84d6fca 1606 bfd_preserve_finish (abfd, &preserve);
3af9a47b 1607 return abfd->xvec;
e84d6fca
AM
1608
1609 wrong:
1610 bfd_set_error (bfd_error_wrong_format);
1611
1612 fail:
1613 if (preserve.marker != NULL)
1614 bfd_preserve_restore (abfd, &preserve);
1615 return NULL;
3af9a47b
NC
1616}
1617
1618const bfd_target *
116c20d2 1619bfd_mach_o_core_p (bfd *abfd)
3af9a47b 1620{
e84d6fca 1621 struct bfd_preserve preserve;
3af9a47b
NC
1622 bfd_mach_o_header header;
1623
e84d6fca 1624 preserve.marker = NULL;
3af9a47b 1625 if (bfd_mach_o_read_header (abfd, &header) != 0)
e84d6fca 1626 goto wrong;
3af9a47b 1627
e84d6fca
AM
1628 if (! (header.byteorder == BFD_ENDIAN_BIG
1629 || header.byteorder == BFD_ENDIAN_LITTLE))
3af9a47b 1630 {
e84d6fca
AM
1631 fprintf (stderr, "unknown header byte-order value 0x%lx\n",
1632 (long) header.byteorder);
3af9a47b
NC
1633 abort ();
1634 }
1635
e84d6fca
AM
1636 if (! ((header.byteorder == BFD_ENDIAN_BIG
1637 && abfd->xvec->byteorder == BFD_ENDIAN_BIG
1638 && abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
1639 || (header.byteorder == BFD_ENDIAN_LITTLE
1640 && abfd->xvec->byteorder == BFD_ENDIAN_LITTLE
1641 && abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)))
1642 goto wrong;
3af9a47b
NC
1643
1644 if (header.filetype != BFD_MACH_O_MH_CORE)
e84d6fca 1645 goto wrong;
3af9a47b 1646
e84d6fca
AM
1647 preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct));
1648 if (preserve.marker == NULL
1649 || !bfd_preserve_save (abfd, &preserve))
1650 goto fail;
a95a4550 1651
e84d6fca
AM
1652 if (bfd_mach_o_scan (abfd, &header,
1653 (bfd_mach_o_data_struct *) preserve.marker) != 0)
1654 goto wrong;
1655
1656 bfd_preserve_finish (abfd, &preserve);
3af9a47b 1657 return abfd->xvec;
e84d6fca
AM
1658
1659 wrong:
1660 bfd_set_error (bfd_error_wrong_format);
1661
1662 fail:
1663 if (preserve.marker != NULL)
1664 bfd_preserve_restore (abfd, &preserve);
1665 return NULL;
3af9a47b
NC
1666}
1667
1668typedef struct mach_o_fat_archentry
1669{
1670 unsigned long cputype;
1671 unsigned long cpusubtype;
1672 unsigned long offset;
1673 unsigned long size;
1674 unsigned long align;
1675 bfd *abfd;
1676} mach_o_fat_archentry;
1677
1678typedef struct mach_o_fat_data_struct
1679{
1680 unsigned long magic;
1681 unsigned long nfat_arch;
1682 mach_o_fat_archentry *archentries;
1683} mach_o_fat_data_struct;
1684
1685const bfd_target *
116c20d2 1686bfd_mach_o_archive_p (bfd *abfd)
3af9a47b 1687{
e84d6fca 1688 mach_o_fat_data_struct *adata = NULL;
3af9a47b
NC
1689 unsigned char buf[20];
1690 unsigned long i;
1691
1692 bfd_seek (abfd, 0, SEEK_SET);
1693 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
e84d6fca 1694 goto error;
3af9a47b 1695
116c20d2 1696 adata = bfd_alloc (abfd, sizeof (mach_o_fat_data_struct));
3af9a47b 1697 if (adata == NULL)
e84d6fca 1698 goto error;
a95a4550 1699
3af9a47b
NC
1700 adata->magic = bfd_getb32 (buf);
1701 adata->nfat_arch = bfd_getb32 (buf + 4);
1702 if (adata->magic != 0xcafebabe)
e84d6fca 1703 goto error;
3af9a47b 1704
116c20d2 1705 adata->archentries =
3af9a47b
NC
1706 bfd_alloc (abfd, adata->nfat_arch * sizeof (mach_o_fat_archentry));
1707 if (adata->archentries == NULL)
e84d6fca 1708 goto error;
3af9a47b
NC
1709
1710 for (i = 0; i < adata->nfat_arch; i++)
1711 {
1712 bfd_seek (abfd, 8 + 20 * i, SEEK_SET);
1713
1714 if (bfd_bread ((PTR) buf, 20, abfd) != 20)
e84d6fca 1715 goto error;
3af9a47b
NC
1716 adata->archentries[i].cputype = bfd_getb32 (buf);
1717 adata->archentries[i].cpusubtype = bfd_getb32 (buf + 4);
1718 adata->archentries[i].offset = bfd_getb32 (buf + 8);
1719 adata->archentries[i].size = bfd_getb32 (buf + 12);
1720 adata->archentries[i].align = bfd_getb32 (buf + 16);
1721 adata->archentries[i].abfd = NULL;
1722 }
1723
1724 abfd->tdata.mach_o_fat_data = adata;
1725 return abfd->xvec;
e84d6fca
AM
1726
1727 error:
1728 if (adata != NULL)
1729 bfd_release (abfd, adata);
1730 bfd_set_error (bfd_error_wrong_format);
1731 return NULL;
3af9a47b
NC
1732}
1733
1734bfd *
116c20d2 1735bfd_mach_o_openr_next_archived_file (bfd *archive, bfd *prev)
3af9a47b 1736{
e84d6fca 1737 mach_o_fat_data_struct *adata;
3af9a47b
NC
1738 mach_o_fat_archentry *entry = NULL;
1739 unsigned long i;
1740
e84d6fca 1741 adata = (mach_o_fat_data_struct *) archive->tdata.mach_o_fat_data;
3af9a47b
NC
1742 BFD_ASSERT (adata != NULL);
1743
1744 /* Find index of previous entry. */
1745 if (prev == NULL)
1746 i = 0; /* Start at first one. */
1747 else
1748 {
1749 for (i = 0; i < adata->nfat_arch; i++)
1750 {
1751 if (adata->archentries[i].abfd == prev)
1752 break;
1753 }
1754
1755 if (i == adata->nfat_arch)
1756 {
1757 /* Not found. */
1758 bfd_set_error (bfd_error_bad_value);
a95a4550 1759 return NULL;
3af9a47b
NC
1760 }
1761 i++; /* Get next entry. */
1762 }
a95a4550 1763
3af9a47b
NC
1764 if (i >= adata->nfat_arch)
1765 {
1766 bfd_set_error (bfd_error_no_more_archived_files);
1767 return NULL;
1768 }
1769
1770 entry = &adata->archentries[i];
1771 if (entry->abfd == NULL)
1772 {
1773 bfd *nbfd = _bfd_new_bfd_contained_in (archive);
1774 char *s = NULL;
1775
1776 if (nbfd == NULL)
1777 return NULL;
1778
1779 nbfd->origin = entry->offset;
1780 s = bfd_malloc (strlen (archive->filename) + 1);
1781 if (s == NULL)
1782 return NULL;
1783 strcpy (s, archive->filename);
1784 nbfd->filename = s;
1785 nbfd->iostream = NULL;
1786 entry->abfd = nbfd;
1787 }
1788
1789 return entry->abfd;
1790}
1791
e84d6fca 1792int
116c20d2
NC
1793bfd_mach_o_lookup_section (bfd *abfd,
1794 asection *section,
1795 bfd_mach_o_load_command **mcommand,
1796 bfd_mach_o_section **msection)
3af9a47b
NC
1797{
1798 struct mach_o_data_struct *md = abfd->tdata.mach_o_data;
1799 unsigned int i, j, num;
1800
1801 bfd_mach_o_load_command *ncmd = NULL;
1802 bfd_mach_o_section *nsect = NULL;
1803
1804 BFD_ASSERT (mcommand != NULL);
1805 BFD_ASSERT (msection != NULL);
1806
1807 num = 0;
1808 for (i = 0; i < md->header.ncmds; i++)
1809 {
1810 struct bfd_mach_o_load_command *cmd = &md->commands[i];
1811 struct bfd_mach_o_segment_command *seg = NULL;
1812
1813 if (cmd->type != BFD_MACH_O_LC_SEGMENT)
1814 continue;
1815 seg = &cmd->command.segment;
a95a4550 1816
3af9a47b
NC
1817 if (seg->segment == section)
1818 {
1819 if (num == 0)
1820 ncmd = cmd;
1821 num++;
1822 }
1823
1824 for (j = 0; j < seg->nsects; j++)
1825 {
1826 struct bfd_mach_o_section *sect = &seg->sections[j];
1827
1828 if (sect->bfdsection == section)
1829 {
1830 if (num == 0)
1831 nsect = sect;
1832 num++;
1833 }
1834 }
1835 }
a95a4550 1836
3af9a47b
NC
1837 *mcommand = ncmd;
1838 *msection = nsect;
1839 return num;
1840}
1841
1842int
116c20d2
NC
1843bfd_mach_o_lookup_command (bfd *abfd,
1844 bfd_mach_o_load_command_type type,
1845 bfd_mach_o_load_command **mcommand)
3af9a47b
NC
1846{
1847 struct mach_o_data_struct *md = NULL;
1848 bfd_mach_o_load_command *ncmd = NULL;
1849 unsigned int i, num;
1850
1851 md = abfd->tdata.mach_o_data;
1852
1853 BFD_ASSERT (md != NULL);
1854 BFD_ASSERT (mcommand != NULL);
1855
1856 num = 0;
1857 for (i = 0; i < md->header.ncmds; i++)
1858 {
1859 struct bfd_mach_o_load_command *cmd = &md->commands[i];
1860
1861 if (cmd->type != type)
1862 continue;
1863
1864 if (num == 0)
1865 ncmd = cmd;
1866 num++;
1867 }
1868
1869 *mcommand = ncmd;
1870 return num;
1871}
1872
1873unsigned long
116c20d2 1874bfd_mach_o_stack_addr (enum bfd_mach_o_cpu_type type)
3af9a47b
NC
1875{
1876 switch (type)
1877 {
1878 case BFD_MACH_O_CPU_TYPE_MC680x0:
1879 return 0x04000000;
1880 case BFD_MACH_O_CPU_TYPE_MC88000:
1881 return 0xffffe000;
1882 case BFD_MACH_O_CPU_TYPE_POWERPC:
1883 return 0xc0000000;
1884 case BFD_MACH_O_CPU_TYPE_I386:
1885 return 0xc0000000;
1886 case BFD_MACH_O_CPU_TYPE_SPARC:
1887 return 0xf0000000;
1888 case BFD_MACH_O_CPU_TYPE_I860:
1889 return 0;
1890 case BFD_MACH_O_CPU_TYPE_HPPA:
e84d6fca 1891 return 0xc0000000 - 0x04000000;
3af9a47b
NC
1892 default:
1893 return 0;
1894 }
1895}
1896
1897int
116c20d2
NC
1898bfd_mach_o_core_fetch_environment (bfd *abfd,
1899 unsigned char **rbuf,
1900 unsigned int *rlen)
3af9a47b
NC
1901{
1902 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
1903 unsigned long stackaddr = bfd_mach_o_stack_addr (mdata->header.cputype);
1904 unsigned int i = 0;
1905
1906 for (i = 0; i < mdata->header.ncmds; i++)
1907 {
1908 bfd_mach_o_load_command *cur = &mdata->commands[i];
1909 bfd_mach_o_segment_command *seg = NULL;
1910
1911 if (cur->type != BFD_MACH_O_LC_SEGMENT)
1912 continue;
1913
1914 seg = &cur->command.segment;
1915
1916 if ((seg->vmaddr + seg->vmsize) == stackaddr)
1917 {
1918 unsigned long start = seg->fileoff;
1919 unsigned long end = seg->fileoff + seg->filesize;
1920 unsigned char *buf = bfd_malloc (1024);
1921 unsigned long size = 1024;
1922
1923 for (;;)
1924 {
1925 bfd_size_type nread = 0;
1926 unsigned long offset;
1927 int found_nonnull = 0;
1928
1929 if (size > (end - start))
1930 size = (end - start);
1931
1932 buf = bfd_realloc (buf, size);
1933
1934 bfd_seek (abfd, end - size, SEEK_SET);
1935 nread = bfd_bread (buf, size, abfd);
a95a4550 1936
3af9a47b
NC
1937 if (nread != size)
1938 return -1;
a95a4550 1939
3af9a47b
NC
1940 for (offset = 4; offset <= size; offset += 4)
1941 {
e84d6fca 1942 unsigned long val;
3af9a47b 1943
e84d6fca 1944 val = *((unsigned long *) (buf + size - offset));
3af9a47b
NC
1945 if (! found_nonnull)
1946 {
1947 if (val != 0)
1948 found_nonnull = 1;
1949 }
1950 else if (val == 0x0)
1951 {
e84d6fca
AM
1952 unsigned long bottom;
1953 unsigned long top;
3af9a47b 1954
e84d6fca
AM
1955 bottom = seg->fileoff + seg->filesize - offset;
1956 top = seg->fileoff + seg->filesize - 4;
3af9a47b
NC
1957 *rbuf = bfd_malloc (top - bottom);
1958 *rlen = top - bottom;
1959
1960 memcpy (*rbuf, buf + size - *rlen, *rlen);
1961 return 0;
1962 }
1963 }
1964
1965 if (size == (end - start))
1966 break;
1967
1968 size *= 2;
1969 }
1970 }
1971 }
1972
1973 return -1;
1974}
1975
1976char *
116c20d2 1977bfd_mach_o_core_file_failing_command (bfd *abfd)
3af9a47b
NC
1978{
1979 unsigned char *buf = NULL;
1980 unsigned int len = 0;
1981 int ret = -1;
1982
1983 ret = bfd_mach_o_core_fetch_environment (abfd, &buf, &len);
1984 if (ret < 0)
1985 return NULL;
1986
f075ee0c 1987 return (char *) buf;
3af9a47b
NC
1988}
1989
1990int
116c20d2 1991bfd_mach_o_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
3af9a47b
NC
1992{
1993 return 0;
1994}
1995
b34976b6 1996bfd_boolean
116c20d2
NC
1997bfd_mach_o_core_file_matches_executable_p (bfd *core_bfd ATTRIBUTE_UNUSED,
1998 bfd *exec_bfd ATTRIBUTE_UNUSED)
3af9a47b 1999{
b34976b6 2000 return TRUE;
3af9a47b
NC
2001}
2002
116c20d2
NC
2003#define TARGET_NAME mach_o_be_vec
2004#define TARGET_STRING "mach-o-be"
2005#define TARGET_BIG_ENDIAN 1
2006#define TARGET_ARCHIVE 0
3af9a47b
NC
2007
2008#include "mach-o-target.c"
2009
2010#undef TARGET_NAME
2011#undef TARGET_STRING
2012#undef TARGET_BIG_ENDIAN
2013#undef TARGET_ARCHIVE
2014
116c20d2
NC
2015#define TARGET_NAME mach_o_le_vec
2016#define TARGET_STRING "mach-o-le"
2017#define TARGET_BIG_ENDIAN 0
2018#define TARGET_ARCHIVE 0
3af9a47b
NC
2019
2020#include "mach-o-target.c"
2021
2022#undef TARGET_NAME
2023#undef TARGET_STRING
2024#undef TARGET_BIG_ENDIAN
2025#undef TARGET_ARCHIVE
2026
116c20d2
NC
2027#define TARGET_NAME mach_o_fat_vec
2028#define TARGET_STRING "mach-o-fat"
2029#define TARGET_BIG_ENDIAN 1
2030#define TARGET_ARCHIVE 1
3af9a47b
NC
2031
2032#include "mach-o-target.c"
2033
2034#undef TARGET_NAME
2035#undef TARGET_STRING
2036#undef TARGET_BIG_ENDIAN
2037#undef TARGET_ARCHIVE
This page took 0.263099 seconds and 4 git commands to generate.