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