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