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