* ldlang.c (lang_check_section_addresses): Ignore non-loadable
[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"
15e1c58a 27#include "aout/stab_gnu.h"
3af9a47b
NC
28#include <ctype.h>
29
30#ifndef BFD_IO_FUNCS
31#define BFD_IO_FUNCS 0
32#endif
33
116c20d2
NC
34#define bfd_mach_o_mkarchive _bfd_noarchive_mkarchive
35#define bfd_mach_o_read_ar_hdr _bfd_noarchive_read_ar_hdr
36#define bfd_mach_o_slurp_armap _bfd_noarchive_slurp_armap
37#define bfd_mach_o_slurp_extended_name_table _bfd_noarchive_slurp_extended_name_table
38#define bfd_mach_o_construct_extended_name_table _bfd_noarchive_construct_extended_name_table
39#define bfd_mach_o_truncate_arname _bfd_noarchive_truncate_arname
40#define bfd_mach_o_write_armap _bfd_noarchive_write_armap
41#define bfd_mach_o_get_elt_at_index _bfd_noarchive_get_elt_at_index
42#define bfd_mach_o_generic_stat_arch_elt _bfd_noarchive_generic_stat_arch_elt
43#define bfd_mach_o_update_armap_timestamp _bfd_noarchive_update_armap_timestamp
44#define bfd_mach_o_close_and_cleanup _bfd_generic_close_and_cleanup
45#define bfd_mach_o_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
46#define bfd_mach_o_new_section_hook _bfd_generic_new_section_hook
47#define bfd_mach_o_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
48#define bfd_mach_o_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name
49#define bfd_mach_o_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
50#define bfd_mach_o_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name
51#define bfd_mach_o_get_lineno _bfd_nosymbols_get_lineno
52#define bfd_mach_o_find_nearest_line _bfd_nosymbols_find_nearest_line
4ab527b0 53#define bfd_mach_o_find_inliner_info _bfd_nosymbols_find_inliner_info
116c20d2
NC
54#define bfd_mach_o_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
55#define bfd_mach_o_read_minisymbols _bfd_generic_read_minisymbols
56#define bfd_mach_o_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
3af9a47b 57#define bfd_mach_o_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
116c20d2
NC
58#define bfd_mach_o_bfd_relax_section bfd_generic_relax_section
59#define bfd_mach_o_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
60#define bfd_mach_o_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
61#define bfd_mach_o_bfd_link_add_symbols _bfd_generic_link_add_symbols
62#define bfd_mach_o_bfd_link_just_syms _bfd_generic_link_just_syms
63#define bfd_mach_o_bfd_final_link _bfd_generic_final_link
64#define bfd_mach_o_bfd_link_split_section _bfd_generic_link_split_section
65#define bfd_mach_o_set_arch_mach bfd_default_set_arch_mach
66#define bfd_mach_o_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
67#define bfd_mach_o_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
116c20d2
NC
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
3023e3f6 75#define bfd_mach_o_bfd_define_common_symbol bfd_generic_define_common_symbol
116c20d2 76#define bfd_mach_o_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data
69d246d9 77#define bfd_mach_o_core_file_matches_executable_p generic_core_file_matches_executable_p
116c20d2 78
1e8a024a
TG
79static unsigned int
80bfd_mach_o_version (bfd *abfd)
81{
82 bfd_mach_o_data_struct *mdata = NULL;
83
84 BFD_ASSERT (bfd_mach_o_valid (abfd));
85 mdata = abfd->tdata.mach_o_data;
86
87 return mdata->header.version;
88}
89
b34976b6 90bfd_boolean
116c20d2 91bfd_mach_o_valid (bfd *abfd)
3af9a47b
NC
92{
93 if (abfd == NULL || abfd->xvec == NULL)
94 return 0;
95
96 if (! ((abfd->xvec == &mach_o_be_vec)
97 || (abfd->xvec == &mach_o_le_vec)
98 || (abfd->xvec == &mach_o_fat_vec)))
99 return 0;
100
101 if (abfd->tdata.mach_o_data == NULL)
102 return 0;
103 return 1;
104}
105
106/* Copy any private info we understand from the input symbol
107 to the output symbol. */
108
b34976b6 109static bfd_boolean
116c20d2
NC
110bfd_mach_o_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
111 asymbol *isymbol ATTRIBUTE_UNUSED,
112 bfd *obfd ATTRIBUTE_UNUSED,
113 asymbol *osymbol ATTRIBUTE_UNUSED)
3af9a47b 114{
b34976b6 115 return TRUE;
3af9a47b
NC
116}
117
118/* Copy any private info we understand from the input section
119 to the output section. */
120
b34976b6 121static bfd_boolean
116c20d2
NC
122bfd_mach_o_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
123 asection *isection ATTRIBUTE_UNUSED,
124 bfd *obfd ATTRIBUTE_UNUSED,
125 asection *osection ATTRIBUTE_UNUSED)
3af9a47b 126{
b34976b6 127 return TRUE;
3af9a47b
NC
128}
129
130/* Copy any private info we understand from the input bfd
131 to the output bfd. */
132
b34976b6 133static bfd_boolean
116c20d2 134bfd_mach_o_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
3af9a47b
NC
135{
136 BFD_ASSERT (bfd_mach_o_valid (ibfd));
137 BFD_ASSERT (bfd_mach_o_valid (obfd));
138
139 obfd->tdata.mach_o_data = ibfd->tdata.mach_o_data;
140 obfd->tdata.mach_o_data->ibfd = ibfd;
b34976b6 141 return TRUE;
3af9a47b
NC
142}
143
144static long
116c20d2 145bfd_mach_o_count_symbols (bfd *abfd)
3af9a47b
NC
146{
147 bfd_mach_o_data_struct *mdata = NULL;
148 long nsyms = 0;
149 unsigned long i;
a95a4550 150
3af9a47b
NC
151 BFD_ASSERT (bfd_mach_o_valid (abfd));
152 mdata = abfd->tdata.mach_o_data;
153
154 for (i = 0; i < mdata->header.ncmds; i++)
155 if (mdata->commands[i].type == BFD_MACH_O_LC_SYMTAB)
156 {
157 bfd_mach_o_symtab_command *sym = &mdata->commands[i].command.symtab;
158 nsyms += sym->nsyms;
159 }
160
161 return nsyms;
162}
163
164static long
116c20d2 165bfd_mach_o_get_symtab_upper_bound (bfd *abfd)
3af9a47b
NC
166{
167 long nsyms = bfd_mach_o_count_symbols (abfd);
168
169 if (nsyms < 0)
170 return nsyms;
171
172 return ((nsyms + 1) * sizeof (asymbol *));
173}
174
175static long
116c20d2 176bfd_mach_o_canonicalize_symtab (bfd *abfd, asymbol **alocation)
3af9a47b
NC
177{
178 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
179 long nsyms = bfd_mach_o_count_symbols (abfd);
180 asymbol **csym = alocation;
181 unsigned long i, j;
182
183 if (nsyms < 0)
184 return nsyms;
185
186 for (i = 0; i < mdata->header.ncmds; i++)
187 {
188 if (mdata->commands[i].type == BFD_MACH_O_LC_SYMTAB)
189 {
190 bfd_mach_o_symtab_command *sym = &mdata->commands[i].command.symtab;
191
192 if (bfd_mach_o_scan_read_symtab_symbols (abfd, &mdata->commands[i].command.symtab) != 0)
193 {
6cee3f79 194 fprintf (stderr, "bfd_mach_o_canonicalize_symtab: unable to load symbols for section %lu\n", i);
3af9a47b
NC
195 return 0;
196 }
197
198 BFD_ASSERT (sym->symbols != NULL);
199
200 for (j = 0; j < sym->nsyms; j++)
201 {
202 BFD_ASSERT (csym < (alocation + nsyms));
203 *csym++ = &sym->symbols[j];
204 }
205 }
206 }
207
208 *csym++ = NULL;
a95a4550 209
3af9a47b
NC
210 return nsyms;
211}
212
213static void
116c20d2
NC
214bfd_mach_o_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
215 asymbol *symbol,
216 symbol_info *ret)
3af9a47b
NC
217{
218 bfd_symbol_info (symbol, ret);
219}
220
221static void
116c20d2
NC
222bfd_mach_o_print_symbol (bfd *abfd,
223 PTR afile,
224 asymbol *symbol,
225 bfd_print_symbol_type how)
3af9a47b
NC
226{
227 FILE *file = (FILE *) afile;
15e1c58a
TG
228 unsigned char ntype;
229 unsigned char nsect;
230 unsigned int ndesc;
231 const char *name;
3af9a47b
NC
232
233 switch (how)
234 {
235 case bfd_print_symbol_name:
236 fprintf (file, "%s", symbol->name);
237 break;
238 default:
239 bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
15e1c58a
TG
240 ntype = BFD_MACH_O_SYM_NTYPE (symbol);
241 nsect = BFD_MACH_O_SYM_NSECT (symbol);
242 ndesc = BFD_MACH_O_SYM_NDESC (symbol);
243 if (ntype & BFD_MACH_O_N_STAB)
244 name = bfd_get_stab_name (ntype);
245 else
246 switch (ntype & BFD_MACH_O_N_TYPE)
247 {
248 case BFD_MACH_O_N_UNDF:
249 name = "UND";
250 break;
251 case BFD_MACH_O_N_ABS:
252 name = "ABS";
253 break;
254 case BFD_MACH_O_N_INDR:
255 name = "INDR";
256 break;
257 case BFD_MACH_O_N_PBUD:
258 name = "PBUD";
259 break;
260 case BFD_MACH_O_N_SECT:
261 name = "SECT";
262 break;
263 default:
264 name = "???";
265 break;
266 }
267 if (name == NULL)
268 name = "";
269 fprintf (file, " %02x %-6s %02x %04x", ntype, name, nsect, ndesc);
270 if ((ntype & BFD_MACH_O_N_STAB) == 0
271 && (ntype & BFD_MACH_O_N_TYPE) == BFD_MACH_O_N_SECT)
272 fprintf (file, " %-5s", symbol->section->name);
273 fprintf (file, " %s", symbol->name);
3af9a47b
NC
274 }
275}
276
277static void
116c20d2
NC
278bfd_mach_o_convert_architecture (bfd_mach_o_cpu_type mtype,
279 bfd_mach_o_cpu_subtype msubtype ATTRIBUTE_UNUSED,
280 enum bfd_architecture *type,
281 unsigned long *subtype)
3af9a47b
NC
282{
283 *subtype = bfd_arch_unknown;
284
285 switch (mtype)
286 {
287 case BFD_MACH_O_CPU_TYPE_VAX: *type = bfd_arch_vax; break;
288 case BFD_MACH_O_CPU_TYPE_MC680x0: *type = bfd_arch_m68k; break;
1e8a024a
TG
289 case BFD_MACH_O_CPU_TYPE_I386:
290 *type = bfd_arch_i386;
291 *subtype = bfd_mach_i386_i386;
292 break;
293 case BFD_MACH_O_CPU_TYPE_X86_64:
294 *type = bfd_arch_i386;
295 *subtype = bfd_mach_x86_64;
296 break;
3af9a47b
NC
297 case BFD_MACH_O_CPU_TYPE_MIPS: *type = bfd_arch_mips; break;
298 case BFD_MACH_O_CPU_TYPE_MC98000: *type = bfd_arch_m98k; break;
299 case BFD_MACH_O_CPU_TYPE_HPPA: *type = bfd_arch_hppa; break;
300 case BFD_MACH_O_CPU_TYPE_ARM: *type = bfd_arch_arm; break;
301 case BFD_MACH_O_CPU_TYPE_MC88000: *type = bfd_arch_m88k; break;
1e8a024a
TG
302 case BFD_MACH_O_CPU_TYPE_SPARC:
303 *type = bfd_arch_sparc;
304 *subtype = bfd_mach_sparc;
305 break;
3af9a47b
NC
306 case BFD_MACH_O_CPU_TYPE_I860: *type = bfd_arch_i860; break;
307 case BFD_MACH_O_CPU_TYPE_ALPHA: *type = bfd_arch_alpha; break;
1e8a024a
TG
308 case BFD_MACH_O_CPU_TYPE_POWERPC:
309 *type = bfd_arch_powerpc;
310 *subtype = bfd_mach_ppc;
311 break;
312 case BFD_MACH_O_CPU_TYPE_POWERPC_64:
313 *type = bfd_arch_powerpc;
314 *subtype = bfd_mach_ppc64;
315 break;
3af9a47b 316 default:
1e8a024a
TG
317 *type = bfd_arch_unknown;
318 break;
3af9a47b
NC
319 }
320}
a95a4550 321
116c20d2
NC
322static int
323bfd_mach_o_write_header (bfd *abfd, bfd_mach_o_header *header)
324{
1e8a024a
TG
325 unsigned char buf[32];
326 unsigned int size;
327
328 size = (header->version == 2) ? 32 : 28;
116c20d2
NC
329
330 bfd_h_put_32 (abfd, header->magic, buf + 0);
331 bfd_h_put_32 (abfd, header->cputype, buf + 4);
332 bfd_h_put_32 (abfd, header->cpusubtype, buf + 8);
333 bfd_h_put_32 (abfd, header->filetype, buf + 12);
334 bfd_h_put_32 (abfd, header->ncmds, buf + 16);
335 bfd_h_put_32 (abfd, header->sizeofcmds, buf + 20);
336 bfd_h_put_32 (abfd, header->flags, buf + 24);
337
1e8a024a
TG
338 if (header->version == 2)
339 bfd_h_put_32 (abfd, header->reserved, buf + 28);
340
116c20d2 341 bfd_seek (abfd, 0, SEEK_SET);
1e8a024a 342 if (bfd_bwrite ((PTR) buf, size, abfd) != size)
116c20d2
NC
343 return -1;
344
345 return 0;
346}
347
348static int
1e8a024a 349bfd_mach_o_scan_write_thread (bfd *abfd, bfd_mach_o_load_command *command)
116c20d2
NC
350{
351 bfd_mach_o_thread_command *cmd = &command->command.thread;
352 unsigned int i;
353 unsigned char buf[8];
354 bfd_vma offset;
355 unsigned int nflavours;
356
357 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
358 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
359
360 offset = 8;
361 nflavours = 0;
362 for (i = 0; i < cmd->nflavours; i++)
363 {
364 BFD_ASSERT ((cmd->flavours[i].size % 4) == 0);
365 BFD_ASSERT (cmd->flavours[i].offset == (command->offset + offset + 8));
366
367 bfd_h_put_32 (abfd, cmd->flavours[i].flavour, buf);
368 bfd_h_put_32 (abfd, (cmd->flavours[i].size / 4), buf + 4);
369
370 bfd_seek (abfd, command->offset + offset, SEEK_SET);
371 if (bfd_bwrite ((PTR) buf, 8, abfd) != 8)
372 return -1;
373
374 offset += cmd->flavours[i].size + 8;
375 }
376
377 return 0;
378}
379
380static int
1e8a024a
TG
381bfd_mach_o_scan_write_section_32 (bfd *abfd,
382 bfd_mach_o_section *section,
383 bfd_vma offset)
116c20d2
NC
384{
385 unsigned char buf[68];
386
387 memcpy (buf, section->sectname, 16);
388 memcpy (buf + 16, section->segname, 16);
389 bfd_h_put_32 (abfd, section->addr, buf + 32);
390 bfd_h_put_32 (abfd, section->size, buf + 36);
391 bfd_h_put_32 (abfd, section->offset, buf + 40);
392 bfd_h_put_32 (abfd, section->align, buf + 44);
393 bfd_h_put_32 (abfd, section->reloff, buf + 48);
394 bfd_h_put_32 (abfd, section->nreloc, buf + 52);
395 bfd_h_put_32 (abfd, section->flags, buf + 56);
1e8a024a
TG
396 bfd_h_put_32 (abfd, section->reserved1, buf + 60);
397 bfd_h_put_32 (abfd, section->reserved2, buf + 64);
116c20d2
NC
398
399 bfd_seek (abfd, offset, SEEK_SET);
400 if (bfd_bwrite ((PTR) buf, 68, abfd) != 68)
401 return -1;
402
403 return 0;
404}
405
406static int
1e8a024a
TG
407bfd_mach_o_scan_write_section_64 (bfd *abfd,
408 bfd_mach_o_section *section,
409 bfd_vma offset)
116c20d2 410{
1e8a024a 411 unsigned char buf[80];
116c20d2 412
1e8a024a
TG
413 memcpy (buf, section->sectname, 16);
414 memcpy (buf + 16, section->segname, 16);
415 bfd_h_put_64 (abfd, section->addr, buf + 32);
416 bfd_h_put_64 (abfd, section->size, buf + 40);
417 bfd_h_put_32 (abfd, section->offset, buf + 48);
418 bfd_h_put_32 (abfd, section->align, buf + 52);
419 bfd_h_put_32 (abfd, section->reloff, buf + 56);
420 bfd_h_put_32 (abfd, section->nreloc, buf + 60);
421 bfd_h_put_32 (abfd, section->flags, buf + 64);
422 bfd_h_put_32 (abfd, section->reserved1, buf + 68);
423 bfd_h_put_32 (abfd, section->reserved2, buf + 72);
424 bfd_h_put_32 (abfd, section->reserved3, buf + 76);
116c20d2 425
1e8a024a
TG
426 bfd_seek (abfd, offset, SEEK_SET);
427 if (bfd_bwrite ((PTR) buf, 80, abfd) != 80)
116c20d2
NC
428 return -1;
429
1e8a024a
TG
430 return 0;
431}
432
433static int
434bfd_mach_o_scan_write_section (bfd *abfd,
435 bfd_mach_o_section *section,
436 bfd_vma offset,
437 unsigned int wide)
438{
439 if (wide)
440 return bfd_mach_o_scan_write_section_64 (abfd, section, offset);
441 else
442 return bfd_mach_o_scan_write_section_32 (abfd, section, offset);
443}
444
445static int
446bfd_mach_o_scan_write_segment (bfd *abfd,
447 bfd_mach_o_load_command *command,
448 unsigned int wide)
449{
450 unsigned char buf[64];
451 bfd_mach_o_segment_command *seg = &command->command.segment;
452 unsigned long i;
453
454 if (wide)
455 {
456 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT_64);
457
458 memcpy (buf, seg->segname, 16);
459
460 bfd_h_put_64 (abfd, seg->vmaddr, buf + 16);
461 bfd_h_put_64 (abfd, seg->vmsize, buf + 24);
462 bfd_h_put_64 (abfd, seg->fileoff, buf + 32);
463 bfd_h_put_64 (abfd, seg->filesize, buf + 40);
464 bfd_h_put_32 (abfd, seg->maxprot, buf + 48);
465 bfd_h_put_32 (abfd, seg->initprot, buf + 52);
466 bfd_h_put_32 (abfd, seg->nsects, buf + 56);
467 bfd_h_put_32 (abfd, seg->flags, buf + 60);
468
469 bfd_seek (abfd, command->offset + 8, SEEK_SET);
470 if (bfd_bwrite ((PTR) buf, 64, abfd) != 64)
471 return -1;
472 }
473 else
474 {
475 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
476
477 memcpy (buf, seg->segname, 16);
478
479 bfd_h_put_32 (abfd, seg->vmaddr, buf + 16);
480 bfd_h_put_32 (abfd, seg->vmsize, buf + 20);
481 bfd_h_put_32 (abfd, seg->fileoff, buf + 24);
482 bfd_h_put_32 (abfd, seg->filesize, buf + 28);
483 bfd_h_put_32 (abfd, seg->maxprot, buf + 32);
484 bfd_h_put_32 (abfd, seg->initprot, buf + 36);
485 bfd_h_put_32 (abfd, seg->nsects, buf + 40);
486 bfd_h_put_32 (abfd, seg->flags, buf + 44);
487
488 bfd_seek (abfd, command->offset + 8, SEEK_SET);
489 if (bfd_bwrite ((PTR) buf, 48, abfd) != 48)
490 return -1;
491 }
492
116c20d2
NC
493 {
494 char buf[1024];
495 bfd_vma nbytes = seg->filesize;
496 bfd_vma curoff = seg->fileoff;
497
498 while (nbytes > 0)
499 {
1e8a024a 500 bfd_vma thiswrite = nbytes;
116c20d2 501
1e8a024a
TG
502 if (thiswrite > 1024)
503 thiswrite = 1024;
116c20d2
NC
504
505 bfd_seek (abfd, curoff, SEEK_SET);
1e8a024a 506 if (bfd_bread ((PTR) buf, thiswrite, abfd) != thiswrite)
116c20d2
NC
507 return -1;
508
509 bfd_seek (abfd, curoff, SEEK_SET);
1e8a024a 510 if (bfd_bwrite ((PTR) buf, thiswrite, abfd) != thiswrite)
116c20d2
NC
511 return -1;
512
1e8a024a
TG
513 nbytes -= thiswrite;
514 curoff += thiswrite;
116c20d2
NC
515 }
516 }
517
518 for (i = 0; i < seg->nsects; i++)
519 {
1e8a024a
TG
520 bfd_vma segoff;
521 if (wide)
522 segoff = command->offset + 64 + 8 + (i * 80);
523 else
524 segoff = command->offset + 48 + 8 + (i * 68);
525
526 if (bfd_mach_o_scan_write_section
527 (abfd, &seg->sections[i], segoff, wide) != 0)
116c20d2
NC
528 return -1;
529 }
530
531 return 0;
532}
533
534static int
1e8a024a
TG
535bfd_mach_o_scan_write_segment_32 (bfd *abfd, bfd_mach_o_load_command *command)
536{
537 return bfd_mach_o_scan_write_segment (abfd, command, 0);
538}
539
540static int
541bfd_mach_o_scan_write_segment_64 (bfd *abfd, bfd_mach_o_load_command *command)
542{
543 return bfd_mach_o_scan_write_segment (abfd, command, 1);
544}
545
546static int
547bfd_mach_o_scan_write_symtab_symbols (bfd *abfd, bfd_mach_o_load_command *command)
116c20d2
NC
548{
549 bfd_mach_o_symtab_command *sym = &command->command.symtab;
550 asymbol *s = NULL;
551 unsigned long i;
552
553 for (i = 0; i < sym->nsyms; i++)
554 {
555 unsigned char buf[12];
556 bfd_vma symoff = sym->symoff + (i * 12);
557 unsigned char ntype = 0;
558 unsigned char nsect = 0;
559 short ndesc = 0;
560
561 s = &sym->symbols[i];
562
563 /* Instead just set from the stored values. */
15e1c58a
TG
564 ntype = BFD_MACH_O_SYM_NTYPE (s);
565 nsect = BFD_MACH_O_SYM_NSECT (s);
566 ndesc = BFD_MACH_O_SYM_NDESC (s);
116c20d2
NC
567
568 bfd_h_put_32 (abfd, s->name - sym->strtab, buf);
569 bfd_h_put_8 (abfd, ntype, buf + 4);
570 bfd_h_put_8 (abfd, nsect, buf + 5);
571 bfd_h_put_16 (abfd, ndesc, buf + 6);
572 bfd_h_put_32 (abfd, s->section->vma + s->value, buf + 8);
573
574 bfd_seek (abfd, symoff, SEEK_SET);
575 if (bfd_bwrite ((PTR) buf, 12, abfd) != 12)
576 {
577 fprintf (stderr, "bfd_mach_o_scan_write_symtab_symbols: unable to write %d bytes at %lu\n",
578 12, (unsigned long) symoff);
579 return -1;
580 }
581 }
582
583 return 0;
584}
585
586static int
587bfd_mach_o_scan_write_symtab (bfd *abfd, bfd_mach_o_load_command *command)
588{
589 bfd_mach_o_symtab_command *seg = &command->command.symtab;
590 unsigned char buf[16];
591
592 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
593
594 bfd_h_put_32 (abfd, seg->symoff, buf);
595 bfd_h_put_32 (abfd, seg->nsyms, buf + 4);
596 bfd_h_put_32 (abfd, seg->stroff, buf + 8);
597 bfd_h_put_32 (abfd, seg->strsize, buf + 12);
598
599 bfd_seek (abfd, command->offset + 8, SEEK_SET);
600 if (bfd_bwrite ((PTR) buf, 16, abfd) != 16)
601 return -1;
602
603 if (bfd_mach_o_scan_write_symtab_symbols (abfd, command) != 0)
604 return -1;
605
606 return 0;
607}
608
b34976b6 609static bfd_boolean
116c20d2 610bfd_mach_o_write_contents (bfd *abfd)
3af9a47b
NC
611{
612 unsigned int i;
613 asection *s;
614
615 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
616
617 /* Write data sections first in case they overlap header data to be
618 written later. */
619
620 for (s = abfd->sections; s != (asection *) NULL; s = s->next)
621 ;
622
3af9a47b
NC
623 /* Now write header information. */
624 if (bfd_mach_o_write_header (abfd, &mdata->header) != 0)
b34976b6 625 return FALSE;
3af9a47b
NC
626
627 for (i = 0; i < mdata->header.ncmds; i++)
628 {
629 unsigned char buf[8];
630 bfd_mach_o_load_command *cur = &mdata->commands[i];
631 unsigned long typeflag;
632
633 typeflag = cur->type_required ? cur->type & BFD_MACH_O_LC_REQ_DYLD : cur->type;
634
635 bfd_h_put_32 (abfd, typeflag, buf);
636 bfd_h_put_32 (abfd, cur->len, buf + 4);
637
638 bfd_seek (abfd, cur->offset, SEEK_SET);
639 if (bfd_bwrite ((PTR) buf, 8, abfd) != 8)
b34976b6 640 return FALSE;
3af9a47b
NC
641
642 switch (cur->type)
643 {
644 case BFD_MACH_O_LC_SEGMENT:
1e8a024a
TG
645 if (bfd_mach_o_scan_write_segment_32 (abfd, cur) != 0)
646 return FALSE;
647 break;
648 case BFD_MACH_O_LC_SEGMENT_64:
649 if (bfd_mach_o_scan_write_segment_64 (abfd, cur) != 0)
b34976b6 650 return FALSE;
3af9a47b
NC
651 break;
652 case BFD_MACH_O_LC_SYMTAB:
653 if (bfd_mach_o_scan_write_symtab (abfd, cur) != 0)
b34976b6 654 return FALSE;
3af9a47b
NC
655 break;
656 case BFD_MACH_O_LC_SYMSEG:
657 break;
658 case BFD_MACH_O_LC_THREAD:
659 case BFD_MACH_O_LC_UNIXTHREAD:
660 if (bfd_mach_o_scan_write_thread (abfd, cur) != 0)
b34976b6 661 return FALSE;
3af9a47b
NC
662 break;
663 case BFD_MACH_O_LC_LOADFVMLIB:
664 case BFD_MACH_O_LC_IDFVMLIB:
665 case BFD_MACH_O_LC_IDENT:
666 case BFD_MACH_O_LC_FVMFILE:
667 case BFD_MACH_O_LC_PREPAGE:
668 case BFD_MACH_O_LC_DYSYMTAB:
669 case BFD_MACH_O_LC_LOAD_DYLIB:
670 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
671 case BFD_MACH_O_LC_ID_DYLIB:
672 case BFD_MACH_O_LC_LOAD_DYLINKER:
673 case BFD_MACH_O_LC_ID_DYLINKER:
674 case BFD_MACH_O_LC_PREBOUND_DYLIB:
675 case BFD_MACH_O_LC_ROUTINES:
676 case BFD_MACH_O_LC_SUB_FRAMEWORK:
677 break;
678 default:
679 fprintf (stderr,
680 "unable to write unknown load command 0x%lx\n",
0af1713e 681 (unsigned long) cur->type);
b34976b6 682 return FALSE;
3af9a47b
NC
683 }
684 }
685
b34976b6 686 return TRUE;
3af9a47b
NC
687}
688
689static int
116c20d2 690bfd_mach_o_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
a6b96beb 691 struct bfd_link_info *info ATTRIBUTE_UNUSED)
3af9a47b
NC
692{
693 return 0;
694}
695
696/* Make an empty symbol. This is required only because
697 bfd_make_section_anyway wants to create a symbol for the section. */
698
699static asymbol *
116c20d2 700bfd_mach_o_make_empty_symbol (bfd *abfd)
3af9a47b
NC
701{
702 asymbol *new;
703
116c20d2 704 new = bfd_zalloc (abfd, sizeof (* new));
3af9a47b
NC
705 if (new == NULL)
706 return new;
707 new->the_bfd = abfd;
708 return new;
709}
710
711static int
116c20d2 712bfd_mach_o_read_header (bfd *abfd, bfd_mach_o_header *header)
3af9a47b 713{
1e8a024a
TG
714 unsigned char buf[32];
715 unsigned int size;
edeb6e24 716 bfd_vma (*get32) (const void *) = NULL;
3af9a47b
NC
717
718 bfd_seek (abfd, 0, SEEK_SET);
719
1e8a024a
TG
720 /* Just read the magic number. */
721 if (bfd_bread ((PTR) buf, 4, abfd) != 4)
3af9a47b
NC
722 return -1;
723
724 if (bfd_getb32 (buf) == 0xfeedface)
725 {
726 header->byteorder = BFD_ENDIAN_BIG;
727 header->magic = 0xfeedface;
1e8a024a 728 header->version = 1;
3af9a47b
NC
729 get32 = bfd_getb32;
730 }
731 else if (bfd_getl32 (buf) == 0xfeedface)
732 {
a95a4550 733 header->byteorder = BFD_ENDIAN_LITTLE;
3af9a47b 734 header->magic = 0xfeedface;
1e8a024a
TG
735 header->version = 1;
736 get32 = bfd_getl32;
737 }
738 else if (bfd_getb32 (buf) == 0xfeedfacf)
739 {
740 header->byteorder = BFD_ENDIAN_BIG;
741 header->magic = 0xfeedfacf;
742 header->version = 2;
743 get32 = bfd_getb32;
744 }
745 else if (bfd_getl32 (buf) == 0xfeedfacf)
746 {
747 header->byteorder = BFD_ENDIAN_LITTLE;
748 header->magic = 0xfeedfacf;
749 header->version = 2;
3af9a47b
NC
750 get32 = bfd_getl32;
751 }
752 else
753 {
754 header->byteorder = BFD_ENDIAN_UNKNOWN;
755 return -1;
756 }
a95a4550 757
1e8a024a
TG
758 /* Once the size of the header is known, read the full header. */
759 size = (header->version == 2) ? 32 : 28;
760
761 bfd_seek (abfd, 0, SEEK_SET);
762 if (bfd_bread ((PTR) buf, size, abfd) != size)
763 return -1;
764
3af9a47b
NC
765 header->cputype = (*get32) (buf + 4);
766 header->cpusubtype = (*get32) (buf + 8);
767 header->filetype = (*get32) (buf + 12);
768 header->ncmds = (*get32) (buf + 16);
769 header->sizeofcmds = (*get32) (buf + 20);
770 header->flags = (*get32) (buf + 24);
771
1e8a024a
TG
772 if (header->version == 2)
773 header->reserved = (*get32) (buf + 28);
774
3af9a47b
NC
775 return 0;
776}
777
778static asection *
15e1c58a
TG
779bfd_mach_o_make_bfd_section (bfd *abfd, bfd_mach_o_section *section,
780 unsigned long prot)
3af9a47b
NC
781{
782 asection *bfdsec;
783 char *sname;
784 const char *prefix = "LC_SEGMENT";
785 unsigned int snamelen;
117ed4f8 786 flagword flags;
3af9a47b
NC
787
788 snamelen = strlen (prefix) + 1
789 + strlen (section->segname) + 1
790 + strlen (section->sectname) + 1;
791
116c20d2 792 sname = bfd_alloc (abfd, snamelen);
3af9a47b
NC
793 if (sname == NULL)
794 return NULL;
3af9a47b 795
15e1c58a
TG
796 /* Use canonical dwarf section names for dwarf sections. */
797 if (strcmp (section->segname, "__DWARF") == 0
798 && strncmp (section->sectname, "__", 2) == 0)
799 sprintf (sname, ".%s", section->sectname + 2);
846b9259
TG
800 else if (strcmp (section->segname, "__TEXT") == 0)
801 {
802 if (strcmp (section->sectname, "__eh_frame") == 0)
803 strcpy (sname, ".eh_frame");
804 else if (section->sectname[0])
805 sprintf (sname, "%s.%s", section->segname, section->sectname);
806 else
807 strcpy (sname, section->segname);
808 }
809 else if (strcmp (section->segname, "__DATA") == 0)
810 {
811 if (section->sectname[0])
812 sprintf (sname, "%s.%s", section->segname, section->sectname);
813 else
814 strcpy (sname, section->segname);
815 }
15e1c58a
TG
816 else
817 sprintf (sname, "%s.%s.%s", prefix, section->segname, section->sectname);
818
819 if (section->flags & BFD_MACH_O_S_ATTR_DEBUG)
820 flags = SEC_HAS_CONTENTS | SEC_DEBUGGING;
821 else
822 {
823 flags = SEC_ALLOC;
824 if ((section->flags & BFD_MACH_O_SECTION_TYPE_MASK)
825 != BFD_MACH_O_S_ZEROFILL)
826 {
827 flags |= SEC_HAS_CONTENTS | SEC_LOAD;
828 if (prot & BFD_MACH_O_PROT_EXECUTE)
829 flags |= SEC_CODE;
830 if (prot & BFD_MACH_O_PROT_WRITE)
831 flags |= SEC_DATA;
832 else if (prot & BFD_MACH_O_PROT_READ)
833 flags |= SEC_READONLY;
834 }
835 }
117ed4f8 836 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, flags);
3af9a47b
NC
837 if (bfdsec == NULL)
838 return NULL;
a95a4550 839
3af9a47b
NC
840 bfdsec->vma = section->addr;
841 bfdsec->lma = section->addr;
eea6121a 842 bfdsec->size = section->size;
3af9a47b
NC
843 bfdsec->filepos = section->offset;
844 bfdsec->alignment_power = section->align;
1e8a024a 845 bfdsec->segment_mark = 0;
3af9a47b 846
3af9a47b
NC
847 return bfdsec;
848}
849
850static int
1e8a024a
TG
851bfd_mach_o_scan_read_section_32 (bfd *abfd,
852 bfd_mach_o_section *section,
15e1c58a
TG
853 bfd_vma offset,
854 unsigned long prot)
3af9a47b
NC
855{
856 unsigned char buf[68];
857
858 bfd_seek (abfd, offset, SEEK_SET);
859 if (bfd_bread ((PTR) buf, 68, abfd) != 68)
860 return -1;
a95a4550 861
3af9a47b
NC
862 memcpy (section->sectname, buf, 16);
863 section->sectname[16] = '\0';
864 memcpy (section->segname, buf + 16, 16);
865 section->segname[16] = '\0';
866 section->addr = bfd_h_get_32 (abfd, buf + 32);
867 section->size = bfd_h_get_32 (abfd, buf + 36);
868 section->offset = bfd_h_get_32 (abfd, buf + 40);
869 section->align = bfd_h_get_32 (abfd, buf + 44);
870 section->reloff = bfd_h_get_32 (abfd, buf + 48);
871 section->nreloc = bfd_h_get_32 (abfd, buf + 52);
872 section->flags = bfd_h_get_32 (abfd, buf + 56);
873 section->reserved1 = bfd_h_get_32 (abfd, buf + 60);
874 section->reserved2 = bfd_h_get_32 (abfd, buf + 64);
1e8a024a 875 section->reserved3 = 0;
15e1c58a 876 section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section, prot);
1e8a024a
TG
877
878 if (section->bfdsection == NULL)
879 return -1;
880
881 return 0;
882}
883
884static int
885bfd_mach_o_scan_read_section_64 (bfd *abfd,
886 bfd_mach_o_section *section,
15e1c58a
TG
887 bfd_vma offset,
888 unsigned long prot)
1e8a024a
TG
889{
890 unsigned char buf[80];
891
892 bfd_seek (abfd, offset, SEEK_SET);
893 if (bfd_bread ((PTR) buf, 80, abfd) != 80)
894 return -1;
895
896 memcpy (section->sectname, buf, 16);
897 section->sectname[16] = '\0';
898 memcpy (section->segname, buf + 16, 16);
899 section->segname[16] = '\0';
900 section->addr = bfd_h_get_64 (abfd, buf + 32);
901 section->size = bfd_h_get_64 (abfd, buf + 40);
902 section->offset = bfd_h_get_32 (abfd, buf + 48);
903 section->align = bfd_h_get_32 (abfd, buf + 52);
904 section->reloff = bfd_h_get_32 (abfd, buf + 56);
905 section->nreloc = bfd_h_get_32 (abfd, buf + 60);
906 section->flags = bfd_h_get_32 (abfd, buf + 64);
907 section->reserved1 = bfd_h_get_32 (abfd, buf + 68);
908 section->reserved2 = bfd_h_get_32 (abfd, buf + 72);
909 section->reserved3 = bfd_h_get_32 (abfd, buf + 76);
15e1c58a 910 section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section, prot);
3af9a47b
NC
911
912 if (section->bfdsection == NULL)
913 return -1;
914
915 return 0;
916}
917
1e8a024a
TG
918static int
919bfd_mach_o_scan_read_section (bfd *abfd,
920 bfd_mach_o_section *section,
921 bfd_vma offset,
15e1c58a 922 unsigned long prot,
1e8a024a
TG
923 unsigned int wide)
924{
925 if (wide)
15e1c58a 926 return bfd_mach_o_scan_read_section_64 (abfd, section, offset, prot);
1e8a024a 927 else
15e1c58a 928 return bfd_mach_o_scan_read_section_32 (abfd, section, offset, prot);
1e8a024a
TG
929}
930
3af9a47b 931int
116c20d2
NC
932bfd_mach_o_scan_read_symtab_symbol (bfd *abfd,
933 bfd_mach_o_symtab_command *sym,
934 asymbol *s,
935 unsigned long i)
3af9a47b
NC
936{
937 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
1e8a024a
TG
938 unsigned int wide = (mdata->header.version == 2);
939 unsigned int symwidth = wide ? 16 : 12;
940 bfd_vma symoff = sym->symoff + (i * symwidth);
941 unsigned char buf[16];
3af9a47b
NC
942 unsigned char type = -1;
943 unsigned char section = -1;
944 short desc = -1;
1e8a024a 945 symvalue value = -1;
3af9a47b
NC
946 unsigned long stroff = -1;
947 unsigned int symtype = -1;
948
949 BFD_ASSERT (sym->strtab != NULL);
950
951 bfd_seek (abfd, symoff, SEEK_SET);
1e8a024a 952 if (bfd_bread ((PTR) buf, symwidth, abfd) != symwidth)
3af9a47b
NC
953 {
954 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: unable to read %d bytes at %lu\n",
1e8a024a 955 symwidth, (unsigned long) symoff);
3af9a47b
NC
956 return -1;
957 }
958
959 stroff = bfd_h_get_32 (abfd, buf);
960 type = bfd_h_get_8 (abfd, buf + 4);
961 symtype = (type & 0x0e);
15e1c58a 962 section = bfd_h_get_8 (abfd, buf + 5);
3af9a47b 963 desc = bfd_h_get_16 (abfd, buf + 6);
1e8a024a
TG
964 if (wide)
965 value = bfd_h_get_64 (abfd, buf + 8);
966 else
967 value = bfd_h_get_32 (abfd, buf + 8);
3af9a47b
NC
968
969 if (stroff >= sym->strsize)
970 {
971 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: symbol name out of range (%lu >= %lu)\n",
972 (unsigned long) stroff, (unsigned long) sym->strsize);
a95a4550 973 return -1;
3af9a47b
NC
974 }
975
976 s->the_bfd = abfd;
977 s->name = sym->strtab + stroff;
978 s->value = value;
979 s->udata.i = (type << 24) | (section << 16) | desc;
980 s->flags = 0x0;
981
982 if (type & BFD_MACH_O_N_STAB)
983 {
984 s->flags |= BSF_DEBUGGING;
985 s->section = bfd_und_section_ptr;
15e1c58a
TG
986 switch (type)
987 {
988 case N_FUN:
989 case N_STSYM:
990 case N_LCSYM:
991 case N_BNSYM:
992 case N_SLINE:
993 case N_ENSYM:
994 case N_ECOMM:
995 case N_ECOML:
996 case N_GSYM:
997 if ((section > 0) && (section <= mdata->nsects))
998 {
999 s->section = mdata->sections[section - 1]->bfdsection;
1000 s->value = s->value - mdata->sections[section - 1]->addr;
1001 }
1002 break;
1003 }
3af9a47b
NC
1004 }
1005 else
1006 {
1007 if (type & BFD_MACH_O_N_PEXT)
15e1c58a
TG
1008 s->flags |= BSF_GLOBAL;
1009
3af9a47b 1010 if (type & BFD_MACH_O_N_EXT)
15e1c58a
TG
1011 s->flags |= BSF_GLOBAL;
1012
1013 if (!(type & (BFD_MACH_O_N_PEXT | BFD_MACH_O_N_EXT)))
1014 s->flags |= BSF_LOCAL;
3af9a47b
NC
1015
1016 switch (symtype)
1017 {
1018 case BFD_MACH_O_N_UNDF:
1019 s->section = bfd_und_section_ptr;
1020 break;
1021 case BFD_MACH_O_N_PBUD:
1022 s->section = bfd_und_section_ptr;
1023 break;
1024 case BFD_MACH_O_N_ABS:
1025 s->section = bfd_abs_section_ptr;
1026 break;
1027 case BFD_MACH_O_N_SECT:
1028 if ((section > 0) && (section <= mdata->nsects))
1029 {
15e1c58a
TG
1030 s->section = mdata->sections[section - 1]->bfdsection;
1031 s->value = s->value - mdata->sections[section - 1]->addr;
3af9a47b
NC
1032 }
1033 else
1034 {
1035 /* Mach-O uses 0 to mean "no section"; not an error. */
1036 if (section != 0)
1037 {
1038 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
a95a4550 1039 "symbol \"%s\" specified invalid section %d (max %lu): setting to undefined\n",
3af9a47b
NC
1040 s->name, section, mdata->nsects);
1041 }
1042 s->section = bfd_und_section_ptr;
1043 }
1044 break;
1045 case BFD_MACH_O_N_INDR:
1046 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
a95a4550 1047 "symbol \"%s\" is unsupported 'indirect' reference: setting to undefined\n",
3af9a47b
NC
1048 s->name);
1049 s->section = bfd_und_section_ptr;
1050 break;
1051 default:
1052 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
a95a4550 1053 "symbol \"%s\" specified invalid type field 0x%x: setting to undefined\n",
3af9a47b
NC
1054 s->name, symtype);
1055 s->section = bfd_und_section_ptr;
1056 break;
1057 }
1058 }
1059
1060 return 0;
1061}
1062
1063int
116c20d2
NC
1064bfd_mach_o_scan_read_symtab_strtab (bfd *abfd,
1065 bfd_mach_o_symtab_command *sym)
3af9a47b
NC
1066{
1067 BFD_ASSERT (sym->strtab == NULL);
1068
1069 if (abfd->flags & BFD_IN_MEMORY)
1070 {
1071 struct bfd_in_memory *b;
1072
1073 b = (struct bfd_in_memory *) abfd->iostream;
1074
1075 if ((sym->stroff + sym->strsize) > b->size)
1076 {
1077 bfd_set_error (bfd_error_file_truncated);
1078 return -1;
1079 }
f075ee0c 1080 sym->strtab = (char *) b->buffer + sym->stroff;
3af9a47b
NC
1081 return 0;
1082 }
1083
1084 sym->strtab = bfd_alloc (abfd, sym->strsize);
1085 if (sym->strtab == NULL)
1086 return -1;
1087
1088 bfd_seek (abfd, sym->stroff, SEEK_SET);
1089 if (bfd_bread ((PTR) sym->strtab, sym->strsize, abfd) != sym->strsize)
1090 {
1091 fprintf (stderr, "bfd_mach_o_scan_read_symtab_strtab: unable to read %lu bytes at %lu\n",
1092 sym->strsize, sym->stroff);
a95a4550 1093 return -1;
3af9a47b
NC
1094 }
1095
1096 return 0;
1097}
1098
a95a4550 1099int
116c20d2
NC
1100bfd_mach_o_scan_read_symtab_symbols (bfd *abfd,
1101 bfd_mach_o_symtab_command *sym)
3af9a47b
NC
1102{
1103 unsigned long i;
1104 int ret;
1105
1106 BFD_ASSERT (sym->symbols == NULL);
1107 sym->symbols = bfd_alloc (abfd, sym->nsyms * sizeof (asymbol));
1108
1109 if (sym->symbols == NULL)
1110 {
1111 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbols: unable to allocate memory for symbols\n");
a95a4550 1112 return -1;
3af9a47b 1113 }
a95a4550 1114
3af9a47b
NC
1115 ret = bfd_mach_o_scan_read_symtab_strtab (abfd, sym);
1116 if (ret != 0)
1117 return ret;
1118
1119 for (i = 0; i < sym->nsyms; i++)
1120 {
1121 ret = bfd_mach_o_scan_read_symtab_symbol (abfd, sym, &sym->symbols[i], i);
1122 if (ret != 0)
1123 return ret;
1124 }
a95a4550 1125
3af9a47b
NC
1126 return 0;
1127}
1128
1129int
116c20d2
NC
1130bfd_mach_o_scan_read_dysymtab_symbol (bfd *abfd,
1131 bfd_mach_o_dysymtab_command *dysym,
1132 bfd_mach_o_symtab_command *sym,
1133 asymbol *s,
1134 unsigned long i)
3af9a47b
NC
1135{
1136 unsigned long isymoff = dysym->indirectsymoff + (i * 4);
1137 unsigned long symindex;
1138 unsigned char buf[4];
1139
1140 BFD_ASSERT (i < dysym->nindirectsyms);
a95a4550 1141
3af9a47b
NC
1142 bfd_seek (abfd, isymoff, SEEK_SET);
1143 if (bfd_bread ((PTR) buf, 4, abfd) != 4)
1144 {
1145 fprintf (stderr, "bfd_mach_o_scan_read_dysymtab_symbol: unable to read %lu bytes at %lu\n",
1146 (unsigned long) 4, isymoff);
1147 return -1;
1148 }
1149 symindex = bfd_h_get_32 (abfd, buf);
a95a4550 1150
3af9a47b
NC
1151 return bfd_mach_o_scan_read_symtab_symbol (abfd, sym, s, symindex);
1152}
1153
1154static const char *
116c20d2 1155bfd_mach_o_i386_flavour_string (unsigned int flavour)
3af9a47b
NC
1156{
1157 switch ((int) flavour)
1158 {
15e1c58a
TG
1159 case BFD_MACH_O_x86_THREAD_STATE32: return "x86_THREAD_STATE32";
1160 case BFD_MACH_O_x86_FLOAT_STATE32: return "x86_FLOAT_STATE32";
1161 case BFD_MACH_O_x86_EXCEPTION_STATE32: return "x86_EXCEPTION_STATE32";
1162 case BFD_MACH_O_x86_THREAD_STATE64: return "x86_THREAD_STATE64";
1163 case BFD_MACH_O_x86_FLOAT_STATE64: return "x86_FLOAT_STATE64";
1164 case BFD_MACH_O_x86_EXCEPTION_STATE64: return "x86_EXCEPTION_STATE64";
1165 case BFD_MACH_O_x86_THREAD_STATE: return "x86_THREAD_STATE";
1166 case BFD_MACH_O_x86_FLOAT_STATE: return "x86_FLOAT_STATE";
1167 case BFD_MACH_O_x86_EXCEPTION_STATE: return "x86_EXCEPTION_STATE";
1168 case BFD_MACH_O_x86_DEBUG_STATE32: return "x86_DEBUG_STATE32";
1169 case BFD_MACH_O_x86_DEBUG_STATE64: return "x86_DEBUG_STATE64";
1170 case BFD_MACH_O_x86_DEBUG_STATE: return "x86_DEBUG_STATE";
1171 case BFD_MACH_O_THREAD_STATE_NONE: return "THREAD_STATE_NONE";
3af9a47b
NC
1172 default: return "UNKNOWN";
1173 }
1174}
1175
1176static const char *
116c20d2 1177bfd_mach_o_ppc_flavour_string (unsigned int flavour)
3af9a47b
NC
1178{
1179 switch ((int) flavour)
1180 {
1181 case BFD_MACH_O_PPC_THREAD_STATE: return "PPC_THREAD_STATE";
1182 case BFD_MACH_O_PPC_FLOAT_STATE: return "PPC_FLOAT_STATE";
1183 case BFD_MACH_O_PPC_EXCEPTION_STATE: return "PPC_EXCEPTION_STATE";
1184 case BFD_MACH_O_PPC_VECTOR_STATE: return "PPC_VECTOR_STATE";
1185 default: return "UNKNOWN";
1186 }
1187}
1188
1189static int
116c20d2
NC
1190bfd_mach_o_scan_read_dylinker (bfd *abfd,
1191 bfd_mach_o_load_command *command)
3af9a47b
NC
1192{
1193 bfd_mach_o_dylinker_command *cmd = &command->command.dylinker;
1194 unsigned char buf[4];
1195 unsigned int nameoff;
1196 asection *bfdsec;
1197 char *sname;
1198 const char *prefix;
1199
1200 BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLINKER)
1201 || (command->type == BFD_MACH_O_LC_LOAD_DYLINKER));
1202
1203 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1204 if (bfd_bread ((PTR) buf, 4, abfd) != 4)
1205 return -1;
1206
1207 nameoff = bfd_h_get_32 (abfd, buf + 0);
1208
1209 cmd->name_offset = command->offset + nameoff;
1210 cmd->name_len = command->len - nameoff;
1211
1212 if (command->type == BFD_MACH_O_LC_LOAD_DYLINKER)
1213 prefix = "LC_LOAD_DYLINKER";
1214 else if (command->type == BFD_MACH_O_LC_ID_DYLINKER)
1215 prefix = "LC_ID_DYLINKER";
1216 else
1217 abort ();
1218
116c20d2 1219 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
1220 if (sname == NULL)
1221 return -1;
1222 strcpy (sname, prefix);
1223
117ed4f8 1224 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
3af9a47b
NC
1225 if (bfdsec == NULL)
1226 return -1;
a95a4550 1227
3af9a47b
NC
1228 bfdsec->vma = 0;
1229 bfdsec->lma = 0;
846b9259
TG
1230 bfdsec->size = command->len - nameoff;
1231 bfdsec->filepos = command->offset + nameoff;
3af9a47b 1232 bfdsec->alignment_power = 0;
3af9a47b
NC
1233
1234 cmd->section = bfdsec;
1235
1236 return 0;
1237}
1238
1239static int
116c20d2 1240bfd_mach_o_scan_read_dylib (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1241{
1242 bfd_mach_o_dylib_command *cmd = &command->command.dylib;
1243 unsigned char buf[16];
1244 unsigned int nameoff;
1245 asection *bfdsec;
1246 char *sname;
1247 const char *prefix;
1248
1249 BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLIB)
1250 || (command->type == BFD_MACH_O_LC_LOAD_DYLIB)
1251 || (command->type == BFD_MACH_O_LC_LOAD_WEAK_DYLIB));
1252
1253 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1254 if (bfd_bread ((PTR) buf, 16, abfd) != 16)
1255 return -1;
1256
1257 nameoff = bfd_h_get_32 (abfd, buf + 0);
1258 cmd->timestamp = bfd_h_get_32 (abfd, buf + 4);
1259 cmd->current_version = bfd_h_get_32 (abfd, buf + 8);
1260 cmd->compatibility_version = bfd_h_get_32 (abfd, buf + 12);
1261
1262 cmd->name_offset = command->offset + nameoff;
1263 cmd->name_len = command->len - nameoff;
1264
1265 if (command->type == BFD_MACH_O_LC_LOAD_DYLIB)
1266 prefix = "LC_LOAD_DYLIB";
1267 else if (command->type == BFD_MACH_O_LC_LOAD_WEAK_DYLIB)
1268 prefix = "LC_LOAD_WEAK_DYLIB";
1269 else if (command->type == BFD_MACH_O_LC_ID_DYLIB)
1270 prefix = "LC_ID_DYLIB";
1271 else
1272 abort ();
1273
116c20d2 1274 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
1275 if (sname == NULL)
1276 return -1;
1277 strcpy (sname, prefix);
1278
117ed4f8 1279 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
3af9a47b
NC
1280 if (bfdsec == NULL)
1281 return -1;
a95a4550 1282
3af9a47b
NC
1283 bfdsec->vma = 0;
1284 bfdsec->lma = 0;
eea6121a 1285 bfdsec->size = command->len - 8;
3af9a47b
NC
1286 bfdsec->filepos = command->offset + 8;
1287 bfdsec->alignment_power = 0;
3af9a47b
NC
1288
1289 cmd->section = bfdsec;
1290
1291 return 0;
1292}
1293
1294static int
116c20d2
NC
1295bfd_mach_o_scan_read_prebound_dylib (bfd *abfd ATTRIBUTE_UNUSED,
1296 bfd_mach_o_load_command *command ATTRIBUTE_UNUSED)
3af9a47b
NC
1297{
1298 /* bfd_mach_o_prebound_dylib_command *cmd = &command->command.prebound_dylib; */
1299
1300 BFD_ASSERT (command->type == BFD_MACH_O_LC_PREBOUND_DYLIB);
1301 return 0;
1302}
1303
1304static int
116c20d2 1305bfd_mach_o_scan_read_thread (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1306{
1307 bfd_mach_o_data_struct *mdata = NULL;
1308 bfd_mach_o_thread_command *cmd = &command->command.thread;
1309 unsigned char buf[8];
1310 bfd_vma offset;
1311 unsigned int nflavours;
1312 unsigned int i;
1313
1314 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
1315 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
1316
1317 BFD_ASSERT (bfd_mach_o_valid (abfd));
1318 mdata = abfd->tdata.mach_o_data;
a95a4550 1319
3af9a47b
NC
1320 offset = 8;
1321 nflavours = 0;
1322 while (offset != command->len)
1323 {
1324 if (offset >= command->len)
1325 return -1;
1326
1327 bfd_seek (abfd, command->offset + offset, SEEK_SET);
1328
1329 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
1330 return -1;
1331
1332 offset += 8 + bfd_h_get_32 (abfd, buf + 4) * 4;
1333 nflavours++;
1334 }
1335
116c20d2 1336 cmd->flavours = bfd_alloc (abfd, nflavours * sizeof (bfd_mach_o_thread_flavour));
3af9a47b
NC
1337 if (cmd->flavours == NULL)
1338 return -1;
1339 cmd->nflavours = nflavours;
1340
1341 offset = 8;
1342 nflavours = 0;
1343 while (offset != command->len)
1344 {
1345 if (offset >= command->len)
1346 return -1;
1347
1348 if (nflavours >= cmd->nflavours)
1349 return -1;
1350
1351 bfd_seek (abfd, command->offset + offset, SEEK_SET);
1352
1353 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
1354 return -1;
1355
1356 cmd->flavours[nflavours].flavour = bfd_h_get_32 (abfd, buf);
1357 cmd->flavours[nflavours].offset = command->offset + offset + 8;
1358 cmd->flavours[nflavours].size = bfd_h_get_32 (abfd, buf + 4) * 4;
1359 offset += cmd->flavours[nflavours].size + 8;
1360 nflavours++;
1361 }
1362
1363 for (i = 0; i < nflavours; i++)
1364 {
1365 asection *bfdsec;
1366 unsigned int snamelen;
1367 char *sname;
1368 const char *flavourstr;
1369 const char *prefix = "LC_THREAD";
a95a4550
AM
1370 unsigned int j = 0;
1371
3af9a47b
NC
1372 switch (mdata->header.cputype)
1373 {
1374 case BFD_MACH_O_CPU_TYPE_POWERPC:
1e8a024a 1375 case BFD_MACH_O_CPU_TYPE_POWERPC_64:
3af9a47b
NC
1376 flavourstr = bfd_mach_o_ppc_flavour_string (cmd->flavours[i].flavour);
1377 break;
1378 case BFD_MACH_O_CPU_TYPE_I386:
1e8a024a 1379 case BFD_MACH_O_CPU_TYPE_X86_64:
3af9a47b
NC
1380 flavourstr = bfd_mach_o_i386_flavour_string (cmd->flavours[i].flavour);
1381 break;
1382 default:
1383 flavourstr = "UNKNOWN_ARCHITECTURE";
1384 break;
1385 }
a95a4550 1386
3af9a47b 1387 snamelen = strlen (prefix) + 1 + 20 + 1 + strlen (flavourstr) + 1;
116c20d2 1388 sname = bfd_alloc (abfd, snamelen);
3af9a47b
NC
1389 if (sname == NULL)
1390 return -1;
1391
1392 for (;;)
1393 {
a95a4550
AM
1394 sprintf (sname, "%s.%s.%u", prefix, flavourstr, j);
1395 if (bfd_get_section_by_name (abfd, sname) == NULL)
3af9a47b 1396 break;
a95a4550 1397 j++;
3af9a47b
NC
1398 }
1399
117ed4f8 1400 bfdsec = bfd_make_section_with_flags (abfd, sname, SEC_HAS_CONTENTS);
a95a4550 1401
3af9a47b
NC
1402 bfdsec->vma = 0;
1403 bfdsec->lma = 0;
eea6121a 1404 bfdsec->size = cmd->flavours[i].size;
3af9a47b
NC
1405 bfdsec->filepos = cmd->flavours[i].offset;
1406 bfdsec->alignment_power = 0x0;
3af9a47b
NC
1407
1408 cmd->section = bfdsec;
1409 }
1410
1411 return 0;
1412}
1413
a95a4550 1414static int
116c20d2 1415bfd_mach_o_scan_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1416{
1417 bfd_mach_o_dysymtab_command *seg = &command->command.dysymtab;
1418 unsigned char buf[72];
1419
1420 BFD_ASSERT (command->type == BFD_MACH_O_LC_DYSYMTAB);
1421
1422 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1423 if (bfd_bread ((PTR) buf, 72, abfd) != 72)
1424 return -1;
1425
1426 seg->ilocalsym = bfd_h_get_32 (abfd, buf + 0);
1427 seg->nlocalsym = bfd_h_get_32 (abfd, buf + 4);
1428 seg->iextdefsym = bfd_h_get_32 (abfd, buf + 8);
1429 seg->nextdefsym = bfd_h_get_32 (abfd, buf + 12);
1430 seg->iundefsym = bfd_h_get_32 (abfd, buf + 16);
1431 seg->nundefsym = bfd_h_get_32 (abfd, buf + 20);
1432 seg->tocoff = bfd_h_get_32 (abfd, buf + 24);
1433 seg->ntoc = bfd_h_get_32 (abfd, buf + 28);
1434 seg->modtaboff = bfd_h_get_32 (abfd, buf + 32);
1435 seg->nmodtab = bfd_h_get_32 (abfd, buf + 36);
1436 seg->extrefsymoff = bfd_h_get_32 (abfd, buf + 40);
1437 seg->nextrefsyms = bfd_h_get_32 (abfd, buf + 44);
1438 seg->indirectsymoff = bfd_h_get_32 (abfd, buf + 48);
1439 seg->nindirectsyms = bfd_h_get_32 (abfd, buf + 52);
1440 seg->extreloff = bfd_h_get_32 (abfd, buf + 56);
1441 seg->nextrel = bfd_h_get_32 (abfd, buf + 60);
1442 seg->locreloff = bfd_h_get_32 (abfd, buf + 64);
1443 seg->nlocrel = bfd_h_get_32 (abfd, buf + 68);
1444
1445 return 0;
1446}
1447
a95a4550 1448static int
116c20d2 1449bfd_mach_o_scan_read_symtab (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1450{
1451 bfd_mach_o_symtab_command *seg = &command->command.symtab;
1452 unsigned char buf[16];
1453 asection *bfdsec;
1454 char *sname;
1455 const char *prefix = "LC_SYMTAB.stabs";
1e8a024a 1456 int nlist_size = (bfd_mach_o_version (abfd) > 1) ? 16 : 12;
3af9a47b
NC
1457
1458 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
1459
1460 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1461 if (bfd_bread ((PTR) buf, 16, abfd) != 16)
1462 return -1;
a95a4550 1463
3af9a47b
NC
1464 seg->symoff = bfd_h_get_32 (abfd, buf);
1465 seg->nsyms = bfd_h_get_32 (abfd, buf + 4);
1466 seg->stroff = bfd_h_get_32 (abfd, buf + 8);
1467 seg->strsize = bfd_h_get_32 (abfd, buf + 12);
1468 seg->symbols = NULL;
1469 seg->strtab = NULL;
1470
116c20d2 1471 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
1472 if (sname == NULL)
1473 return -1;
1474 strcpy (sname, prefix);
1475
117ed4f8 1476 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
3af9a47b
NC
1477 if (bfdsec == NULL)
1478 return -1;
a95a4550 1479
3af9a47b
NC
1480 bfdsec->vma = 0;
1481 bfdsec->lma = 0;
1e8a024a 1482 bfdsec->size = seg->nsyms * nlist_size;
3af9a47b
NC
1483 bfdsec->filepos = seg->symoff;
1484 bfdsec->alignment_power = 0;
3af9a47b
NC
1485
1486 seg->stabs_segment = bfdsec;
1487
15e1c58a
TG
1488 if (seg->nsyms != 0)
1489 abfd->flags |= HAS_SYMS;
1490
3af9a47b 1491 prefix = "LC_SYMTAB.stabstr";
116c20d2 1492 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
1493 if (sname == NULL)
1494 return -1;
1495 strcpy (sname, prefix);
1496
117ed4f8 1497 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
3af9a47b
NC
1498 if (bfdsec == NULL)
1499 return -1;
a95a4550 1500
3af9a47b
NC
1501 bfdsec->vma = 0;
1502 bfdsec->lma = 0;
eea6121a 1503 bfdsec->size = seg->strsize;
3af9a47b
NC
1504 bfdsec->filepos = seg->stroff;
1505 bfdsec->alignment_power = 0;
3af9a47b
NC
1506
1507 seg->stabstr_segment = bfdsec;
1508
1509 return 0;
1510}
1511
15e1c58a
TG
1512static int
1513bfd_mach_o_scan_read_uuid (bfd *abfd, bfd_mach_o_load_command *command)
1514{
1515 bfd_mach_o_uuid_command *cmd = &command->command.uuid;
1516 asection *bfdsec;
1517 char *sname;
1518 static const char prefix[] = "LC_UUID";
1519
1520 BFD_ASSERT (command->type == BFD_MACH_O_LC_UUID);
1521
1522 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1523 if (bfd_bread ((PTR) cmd->uuid, 16, abfd) != 16)
1524 return -1;
1525
1526 sname = bfd_alloc (abfd, strlen (prefix) + 1);
1527 if (sname == NULL)
1528 return -1;
1529 strcpy (sname, prefix);
1530
1531 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
1532 if (bfdsec == NULL)
1533 return -1;
1534
1535 bfdsec->vma = 0;
1536 bfdsec->lma = 0;
1537 bfdsec->size = command->len - 8;
1538 bfdsec->filepos = command->offset + 8;
1539 bfdsec->alignment_power = 0;
1540
1541 cmd->section = bfdsec;
1542
1543 return 0;
1544}
1545
3af9a47b 1546static int
1e8a024a
TG
1547bfd_mach_o_scan_read_segment (bfd *abfd,
1548 bfd_mach_o_load_command *command,
1549 unsigned int wide)
3af9a47b 1550{
1e8a024a 1551 unsigned char buf[64];
3af9a47b
NC
1552 bfd_mach_o_segment_command *seg = &command->command.segment;
1553 unsigned long i;
1554 asection *bfdsec;
1555 char *sname;
1556 const char *prefix = "LC_SEGMENT";
1557 unsigned int snamelen;
a95a4550 1558
1e8a024a
TG
1559 if (wide)
1560 {
1561 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT_64);
3af9a47b 1562
1e8a024a
TG
1563 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1564 if (bfd_bread ((PTR) buf, 64, abfd) != 64)
1565 return -1;
3af9a47b 1566
1e8a024a 1567 memcpy (seg->segname, buf, 16);
15e1c58a 1568 seg->segname[16] = '\0';
1e8a024a
TG
1569
1570 seg->vmaddr = bfd_h_get_64 (abfd, buf + 16);
1571 seg->vmsize = bfd_h_get_64 (abfd, buf + 24);
1572 seg->fileoff = bfd_h_get_64 (abfd, buf + 32);
1573 seg->filesize = bfd_h_get_64 (abfd, buf + 40);
1574 seg->maxprot = bfd_h_get_32 (abfd, buf + 48);
1575 seg->initprot = bfd_h_get_32 (abfd, buf + 52);
1576 seg->nsects = bfd_h_get_32 (abfd, buf + 56);
1577 seg->flags = bfd_h_get_32 (abfd, buf + 60);
1578 }
1579 else
1580 {
1581 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
1582
1583 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1584 if (bfd_bread ((PTR) buf, 48, abfd) != 48)
1585 return -1;
1586
1587 memcpy (seg->segname, buf, 16);
15e1c58a 1588 seg->segname[16] = '\0';
1e8a024a
TG
1589
1590 seg->vmaddr = bfd_h_get_32 (abfd, buf + 16);
1591 seg->vmsize = bfd_h_get_32 (abfd, buf + 20);
1592 seg->fileoff = bfd_h_get_32 (abfd, buf + 24);
1593 seg->filesize = bfd_h_get_32 (abfd, buf + 28);
1594 seg->maxprot = bfd_h_get_32 (abfd, buf + 32);
1595 seg->initprot = bfd_h_get_32 (abfd, buf + 36);
1596 seg->nsects = bfd_h_get_32 (abfd, buf + 40);
1597 seg->flags = bfd_h_get_32 (abfd, buf + 44);
1598 }
3af9a47b
NC
1599
1600 snamelen = strlen (prefix) + 1 + strlen (seg->segname) + 1;
116c20d2 1601 sname = bfd_alloc (abfd, snamelen);
3af9a47b
NC
1602 if (sname == NULL)
1603 return -1;
846b9259
TG
1604 if (strcmp (seg->segname, "__TEXT") == 0
1605 || strcmp (seg->segname, "__DATA") == 0
1606 || strcmp (seg->segname, "__IMPORT") == 0
1607 || strcmp (seg->segname, "__LINKEDIT") == 0)
1608 strcpy (sname, seg->segname);
1609 else
1610 sprintf (sname, "%s.%s", prefix, seg->segname);
3af9a47b 1611
1e8a024a 1612 bfdsec = bfd_make_section_anyway (abfd, sname);
3af9a47b
NC
1613 if (bfdsec == NULL)
1614 return -1;
1615
1616 bfdsec->vma = seg->vmaddr;
1617 bfdsec->lma = seg->vmaddr;
eea6121a 1618 bfdsec->size = seg->filesize;
3af9a47b
NC
1619 bfdsec->filepos = seg->fileoff;
1620 bfdsec->alignment_power = 0x0;
15e1c58a 1621 bfdsec->flags = SEC_HAS_CONTENTS;
1e8a024a 1622 bfdsec->segment_mark = 1;
3af9a47b
NC
1623
1624 seg->segment = bfdsec;
1625
1626 if (seg->nsects != 0)
1627 {
116c20d2 1628 seg->sections = bfd_alloc (abfd, seg->nsects * sizeof (bfd_mach_o_section));
3af9a47b
NC
1629 if (seg->sections == NULL)
1630 return -1;
a95a4550 1631
3af9a47b
NC
1632 for (i = 0; i < seg->nsects; i++)
1633 {
1e8a024a
TG
1634 bfd_vma segoff;
1635 if (wide)
1636 segoff = command->offset + 64 + 8 + (i * 80);
1637 else
1638 segoff = command->offset + 48 + 8 + (i * 68);
3af9a47b 1639
1e8a024a 1640 if (bfd_mach_o_scan_read_section
15e1c58a 1641 (abfd, &seg->sections[i], segoff, seg->initprot, wide) != 0)
3af9a47b 1642 return -1;
a95a4550 1643 }
3af9a47b
NC
1644 }
1645
1646 return 0;
1647}
1648
1e8a024a
TG
1649static int
1650bfd_mach_o_scan_read_segment_32 (bfd *abfd, bfd_mach_o_load_command *command)
1651{
1652 return bfd_mach_o_scan_read_segment (abfd, command, 0);
1653}
1654
1655static int
1656bfd_mach_o_scan_read_segment_64 (bfd *abfd, bfd_mach_o_load_command *command)
1657{
1658 return bfd_mach_o_scan_read_segment (abfd, command, 1);
1659}
1660
3af9a47b 1661static int
116c20d2 1662bfd_mach_o_scan_read_command (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1663{
1664 unsigned char buf[8];
1665
1666 bfd_seek (abfd, command->offset, SEEK_SET);
1667 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
1668 return -1;
1669
1670 command->type = (bfd_h_get_32 (abfd, buf) & ~BFD_MACH_O_LC_REQ_DYLD);
e84d6fca
AM
1671 command->type_required = (bfd_h_get_32 (abfd, buf) & BFD_MACH_O_LC_REQ_DYLD
1672 ? 1 : 0);
3af9a47b
NC
1673 command->len = bfd_h_get_32 (abfd, buf + 4);
1674
1675 switch (command->type)
1676 {
1677 case BFD_MACH_O_LC_SEGMENT:
1e8a024a
TG
1678 if (bfd_mach_o_scan_read_segment_32 (abfd, command) != 0)
1679 return -1;
1680 break;
1681 case BFD_MACH_O_LC_SEGMENT_64:
1682 if (bfd_mach_o_scan_read_segment_64 (abfd, command) != 0)
3af9a47b
NC
1683 return -1;
1684 break;
1685 case BFD_MACH_O_LC_SYMTAB:
1686 if (bfd_mach_o_scan_read_symtab (abfd, command) != 0)
1687 return -1;
1688 break;
1689 case BFD_MACH_O_LC_SYMSEG:
1690 break;
1691 case BFD_MACH_O_LC_THREAD:
1692 case BFD_MACH_O_LC_UNIXTHREAD:
1693 if (bfd_mach_o_scan_read_thread (abfd, command) != 0)
1694 return -1;
1695 break;
1696 case BFD_MACH_O_LC_LOAD_DYLINKER:
1697 case BFD_MACH_O_LC_ID_DYLINKER:
1698 if (bfd_mach_o_scan_read_dylinker (abfd, command) != 0)
1699 return -1;
1700 break;
1701 case BFD_MACH_O_LC_LOAD_DYLIB:
1702 case BFD_MACH_O_LC_ID_DYLIB:
1703 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
1704 if (bfd_mach_o_scan_read_dylib (abfd, command) != 0)
1705 return -1;
1706 break;
1707 case BFD_MACH_O_LC_PREBOUND_DYLIB:
1708 if (bfd_mach_o_scan_read_prebound_dylib (abfd, command) != 0)
1709 return -1;
1710 break;
1711 case BFD_MACH_O_LC_LOADFVMLIB:
1712 case BFD_MACH_O_LC_IDFVMLIB:
1713 case BFD_MACH_O_LC_IDENT:
1714 case BFD_MACH_O_LC_FVMFILE:
1715 case BFD_MACH_O_LC_PREPAGE:
1716 case BFD_MACH_O_LC_ROUTINES:
1717 case BFD_MACH_O_LC_SUB_FRAMEWORK:
1718 break;
1719 case BFD_MACH_O_LC_DYSYMTAB:
1720 if (bfd_mach_o_scan_read_dysymtab (abfd, command) != 0)
1721 return -1;
1722 break;
1723 case BFD_MACH_O_LC_SUB_UMBRELLA:
1724 case BFD_MACH_O_LC_SUB_CLIENT:
1725 case BFD_MACH_O_LC_SUB_LIBRARY:
1726 case BFD_MACH_O_LC_TWOLEVEL_HINTS:
1727 case BFD_MACH_O_LC_PREBIND_CKSUM:
1728 break;
15e1c58a
TG
1729 case BFD_MACH_O_LC_UUID:
1730 if (bfd_mach_o_scan_read_uuid (abfd, command) != 0)
1731 return -1;
1732 break;
1733 case BFD_MACH_O_LC_CODE_SIGNATURE:
846b9259
TG
1734 case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO:
1735 case BFD_MACH_O_LC_REEXPORT_DYLIB:
15e1c58a 1736 break;
3af9a47b
NC
1737 default:
1738 fprintf (stderr, "unable to read unknown load command 0x%lx\n",
1739 (unsigned long) command->type);
1740 break;
1741 }
1742
1743 return 0;
1744}
1745
1746static void
116c20d2 1747bfd_mach_o_flatten_sections (bfd *abfd)
3af9a47b
NC
1748{
1749 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
1750 long csect = 0;
1751 unsigned long i, j;
a95a4550 1752
15e1c58a 1753 /* Count total number of sections. */
3af9a47b
NC
1754 mdata->nsects = 0;
1755
1756 for (i = 0; i < mdata->header.ncmds; i++)
1757 {
1e8a024a
TG
1758 if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT
1759 || mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT_64)
3af9a47b 1760 {
e84d6fca
AM
1761 bfd_mach_o_segment_command *seg;
1762
1763 seg = &mdata->commands[i].command.segment;
3af9a47b
NC
1764 mdata->nsects += seg->nsects;
1765 }
1766 }
1767
15e1c58a 1768 /* Allocate sections array. */
e84d6fca
AM
1769 mdata->sections = bfd_alloc (abfd,
1770 mdata->nsects * sizeof (bfd_mach_o_section *));
15e1c58a
TG
1771
1772 /* Fill the array. */
3af9a47b
NC
1773 csect = 0;
1774
1775 for (i = 0; i < mdata->header.ncmds; i++)
1776 {
1e8a024a
TG
1777 if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT
1778 || mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT_64)
3af9a47b 1779 {
e84d6fca 1780 bfd_mach_o_segment_command *seg;
3af9a47b 1781
e84d6fca 1782 seg = &mdata->commands[i].command.segment;
3af9a47b
NC
1783 BFD_ASSERT (csect + seg->nsects <= mdata->nsects);
1784
1785 for (j = 0; j < seg->nsects; j++)
1786 mdata->sections[csect++] = &seg->sections[j];
1787 }
1788 }
1789}
1790
1791int
116c20d2 1792bfd_mach_o_scan_start_address (bfd *abfd)
3af9a47b
NC
1793{
1794 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
1795 bfd_mach_o_thread_command *cmd = NULL;
1796 unsigned long i;
1797
1798 for (i = 0; i < mdata->header.ncmds; i++)
1799 {
1800 if ((mdata->commands[i].type == BFD_MACH_O_LC_THREAD) ||
1801 (mdata->commands[i].type == BFD_MACH_O_LC_UNIXTHREAD))
1802 {
1803 if (cmd == NULL)
1804 cmd = &mdata->commands[i].command.thread;
1805 else
1806 return 0;
1807 }
1808 }
1809
1810 if (cmd == NULL)
1811 return 0;
1812
1813 for (i = 0; i < cmd->nflavours; i++)
1814 {
a95a4550 1815 if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_I386)
e84d6fca 1816 && (cmd->flavours[i].flavour
15e1c58a 1817 == (unsigned long) BFD_MACH_O_x86_THREAD_STATE32))
3af9a47b
NC
1818 {
1819 unsigned char buf[4];
1820
1821 bfd_seek (abfd, cmd->flavours[i].offset + 40, SEEK_SET);
1822
1823 if (bfd_bread (buf, 4, abfd) != 4)
1824 return -1;
1825
1826 abfd->start_address = bfd_h_get_32 (abfd, buf);
1827 }
a95a4550 1828 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC)
3af9a47b
NC
1829 && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE))
1830 {
1831 unsigned char buf[4];
1832
1833 bfd_seek (abfd, cmd->flavours[i].offset + 0, SEEK_SET);
1834
1835 if (bfd_bread (buf, 4, abfd) != 4)
1836 return -1;
1837
1838 abfd->start_address = bfd_h_get_32 (abfd, buf);
1839 }
1e8a024a
TG
1840 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC_64)
1841 && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE_64))
1842 {
1843 unsigned char buf[8];
1844
1845 bfd_seek (abfd, cmd->flavours[i].offset + 0, SEEK_SET);
1846
1847 if (bfd_bread (buf, 8, abfd) != 8)
1848 return -1;
1849
1850 abfd->start_address = bfd_h_get_64 (abfd, buf);
1851 }
1852 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_X86_64)
1853 && (cmd->flavours[i].flavour == BFD_MACH_O_x86_THREAD_STATE64))
1854 {
1855 unsigned char buf[8];
1856
1857 bfd_seek (abfd, cmd->flavours[i].offset + (16 * 8), SEEK_SET);
1858
1859 if (bfd_bread (buf, 8, abfd) != 8)
1860 return -1;
1861
1862 abfd->start_address = bfd_h_get_64 (abfd, buf);
1863 }
3af9a47b
NC
1864 }
1865
1866 return 0;
1867}
1868
1869int
116c20d2
NC
1870bfd_mach_o_scan (bfd *abfd,
1871 bfd_mach_o_header *header,
1872 bfd_mach_o_data_struct *mdata)
3af9a47b
NC
1873{
1874 unsigned int i;
3af9a47b
NC
1875 enum bfd_architecture cputype;
1876 unsigned long cpusubtype;
1e8a024a
TG
1877 unsigned int hdrsize;
1878
1879 hdrsize = (header->version == 2) ? 32 : 28;
3af9a47b 1880
3af9a47b
NC
1881 mdata->header = *header;
1882 mdata->symbols = NULL;
1883
15e1c58a
TG
1884 abfd->flags = abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS);
1885 switch (header->filetype)
1886 {
1887 case BFD_MACH_O_MH_OBJECT:
1888 abfd->flags |= HAS_RELOC;
1889 break;
1890 case BFD_MACH_O_MH_EXECUTE:
1891 abfd->flags |= EXEC_P;
1892 break;
1893 case BFD_MACH_O_MH_DYLIB:
1894 case BFD_MACH_O_MH_BUNDLE:
1895 abfd->flags |= DYNAMIC;
1896 break;
1897 }
1898
3af9a47b
NC
1899 abfd->tdata.mach_o_data = mdata;
1900
e84d6fca
AM
1901 bfd_mach_o_convert_architecture (header->cputype, header->cpusubtype,
1902 &cputype, &cpusubtype);
3af9a47b
NC
1903 if (cputype == bfd_arch_unknown)
1904 {
1905 fprintf (stderr, "bfd_mach_o_scan: unknown architecture 0x%lx/0x%lx\n",
1906 header->cputype, header->cpusubtype);
1907 return -1;
1908 }
1909
1910 bfd_set_arch_mach (abfd, cputype, cpusubtype);
a95a4550 1911
3af9a47b
NC
1912 if (header->ncmds != 0)
1913 {
116c20d2 1914 mdata->commands = bfd_alloc (abfd, header->ncmds * sizeof (bfd_mach_o_load_command));
3af9a47b
NC
1915 if (mdata->commands == NULL)
1916 return -1;
a95a4550 1917
3af9a47b
NC
1918 for (i = 0; i < header->ncmds; i++)
1919 {
1920 bfd_mach_o_load_command *cur = &mdata->commands[i];
1921
1922 if (i == 0)
1e8a024a 1923 cur->offset = hdrsize;
3af9a47b
NC
1924 else
1925 {
1926 bfd_mach_o_load_command *prev = &mdata->commands[i - 1];
1927 cur->offset = prev->offset + prev->len;
1928 }
1929
1930 if (bfd_mach_o_scan_read_command (abfd, cur) < 0)
1931 return -1;
a95a4550 1932 }
3af9a47b
NC
1933 }
1934
1935 if (bfd_mach_o_scan_start_address (abfd) < 0)
7e3102a7 1936 return -1;
3af9a47b
NC
1937
1938 bfd_mach_o_flatten_sections (abfd);
3af9a47b
NC
1939 return 0;
1940}
1941
b34976b6 1942bfd_boolean
116c20d2 1943bfd_mach_o_mkobject (bfd *abfd)
3af9a47b
NC
1944{
1945 bfd_mach_o_data_struct *mdata = NULL;
1946
116c20d2 1947 mdata = bfd_alloc (abfd, sizeof (bfd_mach_o_data_struct));
3af9a47b 1948 if (mdata == NULL)
b34976b6 1949 return FALSE;
3af9a47b
NC
1950 abfd->tdata.mach_o_data = mdata;
1951
1952 mdata->header.magic = 0;
1953 mdata->header.cputype = 0;
1954 mdata->header.cpusubtype = 0;
1955 mdata->header.filetype = 0;
1956 mdata->header.ncmds = 0;
1957 mdata->header.sizeofcmds = 0;
1958 mdata->header.flags = 0;
1959 mdata->header.byteorder = BFD_ENDIAN_UNKNOWN;
1960 mdata->commands = NULL;
1961 mdata->nsymbols = 0;
1962 mdata->symbols = NULL;
1963 mdata->nsects = 0;
1964 mdata->sections = NULL;
1965 mdata->ibfd = NULL;
1966
b34976b6 1967 return TRUE;
3af9a47b
NC
1968}
1969
1970const bfd_target *
116c20d2 1971bfd_mach_o_object_p (bfd *abfd)
3af9a47b 1972{
e84d6fca 1973 struct bfd_preserve preserve;
3af9a47b
NC
1974 bfd_mach_o_header header;
1975
e84d6fca 1976 preserve.marker = NULL;
3af9a47b 1977 if (bfd_mach_o_read_header (abfd, &header) != 0)
e84d6fca 1978 goto wrong;
3af9a47b 1979
e84d6fca
AM
1980 if (! (header.byteorder == BFD_ENDIAN_BIG
1981 || header.byteorder == BFD_ENDIAN_LITTLE))
3af9a47b 1982 {
e84d6fca 1983 fprintf (stderr, "unknown header byte-order value 0x%lx\n",
0af1713e 1984 (unsigned long) header.byteorder);
e84d6fca 1985 goto wrong;
3af9a47b
NC
1986 }
1987
e84d6fca
AM
1988 if (! ((header.byteorder == BFD_ENDIAN_BIG
1989 && abfd->xvec->byteorder == BFD_ENDIAN_BIG
1990 && abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
1991 || (header.byteorder == BFD_ENDIAN_LITTLE
1992 && abfd->xvec->byteorder == BFD_ENDIAN_LITTLE
1993 && abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)))
1994 goto wrong;
3af9a47b 1995
e84d6fca
AM
1996 preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct));
1997 if (preserve.marker == NULL
1998 || !bfd_preserve_save (abfd, &preserve))
1999 goto fail;
3af9a47b 2000
e84d6fca
AM
2001 if (bfd_mach_o_scan (abfd, &header,
2002 (bfd_mach_o_data_struct *) preserve.marker) != 0)
2003 goto wrong;
a95a4550 2004
e84d6fca 2005 bfd_preserve_finish (abfd, &preserve);
3af9a47b 2006 return abfd->xvec;
e84d6fca
AM
2007
2008 wrong:
2009 bfd_set_error (bfd_error_wrong_format);
2010
2011 fail:
2012 if (preserve.marker != NULL)
2013 bfd_preserve_restore (abfd, &preserve);
2014 return NULL;
3af9a47b
NC
2015}
2016
2017const bfd_target *
116c20d2 2018bfd_mach_o_core_p (bfd *abfd)
3af9a47b 2019{
e84d6fca 2020 struct bfd_preserve preserve;
3af9a47b
NC
2021 bfd_mach_o_header header;
2022
e84d6fca 2023 preserve.marker = NULL;
3af9a47b 2024 if (bfd_mach_o_read_header (abfd, &header) != 0)
e84d6fca 2025 goto wrong;
3af9a47b 2026
e84d6fca
AM
2027 if (! (header.byteorder == BFD_ENDIAN_BIG
2028 || header.byteorder == BFD_ENDIAN_LITTLE))
3af9a47b 2029 {
e84d6fca 2030 fprintf (stderr, "unknown header byte-order value 0x%lx\n",
0af1713e 2031 (unsigned long) header.byteorder);
3af9a47b
NC
2032 abort ();
2033 }
2034
e84d6fca
AM
2035 if (! ((header.byteorder == BFD_ENDIAN_BIG
2036 && abfd->xvec->byteorder == BFD_ENDIAN_BIG
2037 && abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
2038 || (header.byteorder == BFD_ENDIAN_LITTLE
2039 && abfd->xvec->byteorder == BFD_ENDIAN_LITTLE
2040 && abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)))
2041 goto wrong;
3af9a47b
NC
2042
2043 if (header.filetype != BFD_MACH_O_MH_CORE)
e84d6fca 2044 goto wrong;
3af9a47b 2045
e84d6fca
AM
2046 preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct));
2047 if (preserve.marker == NULL
2048 || !bfd_preserve_save (abfd, &preserve))
2049 goto fail;
a95a4550 2050
e84d6fca
AM
2051 if (bfd_mach_o_scan (abfd, &header,
2052 (bfd_mach_o_data_struct *) preserve.marker) != 0)
2053 goto wrong;
2054
2055 bfd_preserve_finish (abfd, &preserve);
3af9a47b 2056 return abfd->xvec;
e84d6fca
AM
2057
2058 wrong:
2059 bfd_set_error (bfd_error_wrong_format);
2060
2061 fail:
2062 if (preserve.marker != NULL)
2063 bfd_preserve_restore (abfd, &preserve);
2064 return NULL;
3af9a47b
NC
2065}
2066
2067typedef struct mach_o_fat_archentry
2068{
2069 unsigned long cputype;
2070 unsigned long cpusubtype;
2071 unsigned long offset;
2072 unsigned long size;
2073 unsigned long align;
3af9a47b
NC
2074} mach_o_fat_archentry;
2075
2076typedef struct mach_o_fat_data_struct
2077{
2078 unsigned long magic;
2079 unsigned long nfat_arch;
2080 mach_o_fat_archentry *archentries;
2081} mach_o_fat_data_struct;
2082
2083const bfd_target *
116c20d2 2084bfd_mach_o_archive_p (bfd *abfd)
3af9a47b 2085{
e84d6fca 2086 mach_o_fat_data_struct *adata = NULL;
3af9a47b
NC
2087 unsigned char buf[20];
2088 unsigned long i;
2089
2090 bfd_seek (abfd, 0, SEEK_SET);
2091 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
e84d6fca 2092 goto error;
3af9a47b 2093
116c20d2 2094 adata = bfd_alloc (abfd, sizeof (mach_o_fat_data_struct));
3af9a47b 2095 if (adata == NULL)
e84d6fca 2096 goto error;
a95a4550 2097
3af9a47b
NC
2098 adata->magic = bfd_getb32 (buf);
2099 adata->nfat_arch = bfd_getb32 (buf + 4);
2100 if (adata->magic != 0xcafebabe)
e84d6fca 2101 goto error;
27cc28f9
AS
2102 /* Avoid matching Java bytecode files, which have the same magic number.
2103 In the Java bytecode file format this field contains the JVM version,
2104 which starts at 43.0. */
2105 if (adata->nfat_arch > 30)
2106 goto error;
3af9a47b 2107
116c20d2 2108 adata->archentries =
3af9a47b
NC
2109 bfd_alloc (abfd, adata->nfat_arch * sizeof (mach_o_fat_archentry));
2110 if (adata->archentries == NULL)
e84d6fca 2111 goto error;
3af9a47b
NC
2112
2113 for (i = 0; i < adata->nfat_arch; i++)
2114 {
2115 bfd_seek (abfd, 8 + 20 * i, SEEK_SET);
2116
2117 if (bfd_bread ((PTR) buf, 20, abfd) != 20)
e84d6fca 2118 goto error;
3af9a47b
NC
2119 adata->archentries[i].cputype = bfd_getb32 (buf);
2120 adata->archentries[i].cpusubtype = bfd_getb32 (buf + 4);
2121 adata->archentries[i].offset = bfd_getb32 (buf + 8);
2122 adata->archentries[i].size = bfd_getb32 (buf + 12);
2123 adata->archentries[i].align = bfd_getb32 (buf + 16);
3af9a47b
NC
2124 }
2125
2126 abfd->tdata.mach_o_fat_data = adata;
2127 return abfd->xvec;
e84d6fca
AM
2128
2129 error:
2130 if (adata != NULL)
2131 bfd_release (abfd, adata);
2132 bfd_set_error (bfd_error_wrong_format);
2133 return NULL;
3af9a47b
NC
2134}
2135
2136bfd *
116c20d2 2137bfd_mach_o_openr_next_archived_file (bfd *archive, bfd *prev)
3af9a47b 2138{
e84d6fca 2139 mach_o_fat_data_struct *adata;
3af9a47b
NC
2140 mach_o_fat_archentry *entry = NULL;
2141 unsigned long i;
15e1c58a 2142 bfd *nbfd;
15e1c58a
TG
2143 enum bfd_architecture arch_type;
2144 unsigned long arch_subtype;
3af9a47b 2145
e84d6fca 2146 adata = (mach_o_fat_data_struct *) archive->tdata.mach_o_fat_data;
3af9a47b
NC
2147 BFD_ASSERT (adata != NULL);
2148
2149 /* Find index of previous entry. */
2150 if (prev == NULL)
2151 i = 0; /* Start at first one. */
2152 else
2153 {
2154 for (i = 0; i < adata->nfat_arch; i++)
2155 {
15e1c58a 2156 if (adata->archentries[i].offset == prev->origin)
3af9a47b
NC
2157 break;
2158 }
2159
2160 if (i == adata->nfat_arch)
2161 {
2162 /* Not found. */
2163 bfd_set_error (bfd_error_bad_value);
a95a4550 2164 return NULL;
3af9a47b
NC
2165 }
2166 i++; /* Get next entry. */
2167 }
a95a4550 2168
3af9a47b
NC
2169 if (i >= adata->nfat_arch)
2170 {
2171 bfd_set_error (bfd_error_no_more_archived_files);
2172 return NULL;
2173 }
2174
2175 entry = &adata->archentries[i];
15e1c58a
TG
2176 nbfd = _bfd_new_bfd_contained_in (archive);
2177 if (nbfd == NULL)
2178 return NULL;
2179
2180 nbfd->origin = entry->offset;
2181
2182 bfd_mach_o_convert_architecture (entry->cputype, entry->cpusubtype,
2183 &arch_type, &arch_subtype);
846b9259
TG
2184 /* Create the member filename.
2185 Use FILENAME:ARCH_NAME. */
2186 {
2187 char *s = NULL;
2188 const char *arch_name;
2189 size_t arch_file_len = strlen (bfd_get_filename (archive));
2190
2191 arch_name = bfd_printable_arch_mach (arch_type, arch_subtype);
2192 s = bfd_malloc (arch_file_len + 1 + strlen (arch_name) + 1);
2193 if (s == NULL)
2194 return NULL;
2195 memcpy (s, bfd_get_filename (archive), arch_file_len);
2196 s[arch_file_len] = ':';
2197 strcpy (s + arch_file_len + 1, arch_name);
2198 nbfd->filename = s;
2199 }
15e1c58a 2200 nbfd->iostream = NULL;
846b9259 2201 bfd_set_arch_mach (nbfd, arch_type, arch_subtype);
3af9a47b 2202
15e1c58a 2203 return nbfd;
3af9a47b
NC
2204}
2205
846b9259
TG
2206/* If ABFD format is FORMAT and architecture is ARCH, return it.
2207 If ABFD is a fat image containing a member that corresponds to FORMAT
2208 and ARCH, returns it.
2209 In other case, returns NULL.
2210 This function allows transparent uses of fat images. */
2211bfd *
2212bfd_mach_o_fat_extract (bfd *abfd,
2213 bfd_format format,
2214 const bfd_arch_info_type *arch)
2215{
2216 bfd *res;
2217 mach_o_fat_data_struct *adata;
2218 unsigned int i;
2219
2220 if (bfd_check_format (abfd, format))
2221 {
2222 if (bfd_get_arch_info (abfd) == arch)
2223 return abfd;
2224 return NULL;
2225 }
2226 if (!bfd_check_format (abfd, bfd_archive)
2227 || abfd->xvec != &mach_o_fat_vec)
2228 return NULL;
2229
2230 /* This is a Mach-O fat image. */
2231 adata = (mach_o_fat_data_struct *) abfd->tdata.mach_o_fat_data;
2232 BFD_ASSERT (adata != NULL);
2233
2234 for (i = 0; i < adata->nfat_arch; i++)
2235 {
2236 struct mach_o_fat_archentry *e = &adata->archentries[i];
2237 enum bfd_architecture cpu_type;
2238 unsigned long cpu_subtype;
2239
2240 bfd_mach_o_convert_architecture (e->cputype, e->cpusubtype,
2241 &cpu_type, &cpu_subtype);
2242 if (cpu_type != arch->arch || cpu_subtype != arch->mach)
2243 continue;
2244
2245 /* The architecture is found. */
2246 res = _bfd_new_bfd_contained_in (abfd);
2247 if (res == NULL)
2248 return NULL;
2249
2250 res->origin = e->offset;
2251
2252 res->filename = strdup (abfd->filename);
2253 res->iostream = NULL;
2254
2255 if (bfd_check_format (res, format))
2256 {
2257 BFD_ASSERT (bfd_get_arch_info (res) == arch);
2258 return res;
2259 }
2260 bfd_close (res);
2261 return NULL;
2262 }
2263
2264 return NULL;
2265}
2266
e84d6fca 2267int
116c20d2
NC
2268bfd_mach_o_lookup_section (bfd *abfd,
2269 asection *section,
2270 bfd_mach_o_load_command **mcommand,
2271 bfd_mach_o_section **msection)
3af9a47b
NC
2272{
2273 struct mach_o_data_struct *md = abfd->tdata.mach_o_data;
2274 unsigned int i, j, num;
2275
2276 bfd_mach_o_load_command *ncmd = NULL;
2277 bfd_mach_o_section *nsect = NULL;
2278
2279 BFD_ASSERT (mcommand != NULL);
2280 BFD_ASSERT (msection != NULL);
2281
2282 num = 0;
2283 for (i = 0; i < md->header.ncmds; i++)
2284 {
2285 struct bfd_mach_o_load_command *cmd = &md->commands[i];
2286 struct bfd_mach_o_segment_command *seg = NULL;
2287
1e8a024a
TG
2288 if (cmd->type != BFD_MACH_O_LC_SEGMENT
2289 || cmd->type != BFD_MACH_O_LC_SEGMENT_64)
3af9a47b
NC
2290 continue;
2291 seg = &cmd->command.segment;
a95a4550 2292
3af9a47b
NC
2293 if (seg->segment == section)
2294 {
2295 if (num == 0)
2296 ncmd = cmd;
2297 num++;
2298 }
2299
2300 for (j = 0; j < seg->nsects; j++)
2301 {
2302 struct bfd_mach_o_section *sect = &seg->sections[j];
2303
2304 if (sect->bfdsection == section)
2305 {
2306 if (num == 0)
2307 nsect = sect;
2308 num++;
2309 }
2310 }
2311 }
a95a4550 2312
3af9a47b
NC
2313 *mcommand = ncmd;
2314 *msection = nsect;
2315 return num;
2316}
2317
2318int
116c20d2
NC
2319bfd_mach_o_lookup_command (bfd *abfd,
2320 bfd_mach_o_load_command_type type,
2321 bfd_mach_o_load_command **mcommand)
3af9a47b
NC
2322{
2323 struct mach_o_data_struct *md = NULL;
2324 bfd_mach_o_load_command *ncmd = NULL;
2325 unsigned int i, num;
2326
2327 md = abfd->tdata.mach_o_data;
2328
2329 BFD_ASSERT (md != NULL);
2330 BFD_ASSERT (mcommand != NULL);
2331
2332 num = 0;
2333 for (i = 0; i < md->header.ncmds; i++)
2334 {
2335 struct bfd_mach_o_load_command *cmd = &md->commands[i];
2336
2337 if (cmd->type != type)
2338 continue;
2339
2340 if (num == 0)
2341 ncmd = cmd;
2342 num++;
2343 }
2344
2345 *mcommand = ncmd;
2346 return num;
2347}
2348
2349unsigned long
116c20d2 2350bfd_mach_o_stack_addr (enum bfd_mach_o_cpu_type type)
3af9a47b
NC
2351{
2352 switch (type)
2353 {
2354 case BFD_MACH_O_CPU_TYPE_MC680x0:
2355 return 0x04000000;
2356 case BFD_MACH_O_CPU_TYPE_MC88000:
2357 return 0xffffe000;
2358 case BFD_MACH_O_CPU_TYPE_POWERPC:
2359 return 0xc0000000;
2360 case BFD_MACH_O_CPU_TYPE_I386:
2361 return 0xc0000000;
2362 case BFD_MACH_O_CPU_TYPE_SPARC:
2363 return 0xf0000000;
2364 case BFD_MACH_O_CPU_TYPE_I860:
2365 return 0;
2366 case BFD_MACH_O_CPU_TYPE_HPPA:
e84d6fca 2367 return 0xc0000000 - 0x04000000;
3af9a47b
NC
2368 default:
2369 return 0;
2370 }
2371}
2372
15e1c58a
TG
2373static bfd_boolean
2374bfd_mach_o_bfd_print_private_bfd_data (bfd *abfd, PTR ptr)
2375{
2376 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
2377 FILE *file = (FILE *) ptr;
2378 unsigned int i, j;
2379 unsigned int sec_nbr = 0;
2380
2381 fprintf (file, _("Segments and Sections:\n"));
2382 fprintf (file, _(" #: Segment name Section name Address\n"));
2383
2384 for (i = 0; i < mdata->header.ncmds; i++)
2385 {
2386 bfd_mach_o_segment_command *seg;
2387
2388 if (mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT
2389 && mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT_64)
2390 continue;
2391
2392 seg = &mdata->commands[i].command.segment;
2393
2394 fprintf (file, "[Segment %-16s ", seg->segname);
2395 fprintf_vma (file, seg->vmaddr);
2396 fprintf (file, "-");
2397 fprintf_vma (file, seg->vmaddr + seg->vmsize - 1);
2398 fputc (' ', file);
2399 fputc (seg->initprot & BFD_MACH_O_PROT_READ ? 'r' : '-', file);
2400 fputc (seg->initprot & BFD_MACH_O_PROT_WRITE ? 'w' : '-', file);
2401 fputc (seg->initprot & BFD_MACH_O_PROT_EXECUTE ? 'x' : '-', file);
2402 fprintf (file, "]\n");
2403 for (j = 0; j < seg->nsects; j++)
2404 {
2405 bfd_mach_o_section *sec = &seg->sections[j];
2406 fprintf (file, "%02u: %-16s %-16s ", ++sec_nbr,
2407 sec->segname, sec->sectname);
2408 fprintf_vma (file, sec->addr);
2409 fprintf (file, " ");
2410 fprintf_vma (file, sec->size);
2411 fprintf (file, " %08lx\n", sec->flags);
2412 }
2413 }
2414
2415 for (i = 0; i < mdata->header.ncmds; i++)
2416 {
2417 bfd_mach_o_load_command *cmd = &mdata->commands[i];
2418
2419 switch (cmd->type)
2420 {
2421 case BFD_MACH_O_LC_SEGMENT:
2422 case BFD_MACH_O_LC_SEGMENT_64:
2423 break;
2424 case BFD_MACH_O_LC_UUID:
2425 {
2426 bfd_mach_o_uuid_command *uuid = &cmd->command.uuid;
2427 unsigned int i;
2428
2429 fprintf (file, "\n"
2430 "UUID:");
2431 for (i = 0; i < sizeof (uuid->uuid); i++)
2432 fprintf (file, " %02x", uuid->uuid[i]);
2433 fputc ('\n', file);
2434 }
2435 break;
2436 case BFD_MACH_O_LC_LOAD_DYLIB:
2437 {
2438 bfd_mach_o_dylib_command *dylib = &cmd->command.dylib;
2439 bfd_byte *data = NULL;
2440
2441 if (! bfd_malloc_and_get_section (abfd, dylib->section, &data))
2442 {
2443 if (data != NULL)
2444 free (data);
2445 break;
2446 }
2447 fprintf (file, "\n"
2448 "LOAD_DYLIB: %s\n",
2449 data + dylib->name_offset - cmd->offset - 8);
2450 fprintf (file, " time stamp: 0x%08lx\n",
2451 dylib->timestamp);
2452 fprintf (file, " current version: 0x%08lx\n",
2453 dylib->current_version);
2454 fprintf (file, " comptibility version: 0x%08lx\n",
2455 dylib->compatibility_version);
2456 free (data);
2457 break;
2458 }
2459 case BFD_MACH_O_LC_LOAD_DYLINKER:
2460 {
2461 bfd_mach_o_dylinker_command *linker = &cmd->command.dylinker;
2462 bfd_byte *data = NULL;
2463
2464 if (! bfd_malloc_and_get_section (abfd, linker->section, &data))
2465 {
2466 if (data != NULL)
2467 free (data);
2468 break;
2469 }
2470 fprintf (file, "\n"
2471 "LOAD_DYLINKER: %s\n",
2472 data + linker->name_offset - cmd->offset - 8);
2473 free (data);
2474 break;
2475 }
2476 case BFD_MACH_O_LC_SYMTAB:
2477 {
2478 bfd_mach_o_symtab_command *symtab = &cmd->command.symtab;
2479 fprintf (file, "\n"
2480 "LC_SYMTAB: nsyms: %lu, strsize: %lu\n",
2481 symtab->nsyms, symtab->strsize);
2482 break;
2483 }
2484 case BFD_MACH_O_LC_DYSYMTAB:
2485 {
2486 bfd_mach_o_dysymtab_command *dysymtab = &cmd->command.dysymtab;
2487 fprintf (file, "\n"
2488 "LC_DYSYMTAB:\n"
2489 " local symbols: index: %lu number: %lu\n",
2490 dysymtab->ilocalsym, dysymtab->nlocalsym);
2491 fprintf (file,
2492 " external symbols: index: %lu number: %lu\n",
2493 dysymtab->iextdefsym, dysymtab->nextdefsym);
2494 fprintf (file,
2495 " undefined symbols: index: %lu number: %lu\n",
2496 dysymtab->iundefsym, dysymtab->nundefsym);
2497 fprintf (file,
2498 " ntoc: offset: %lu number: %lu\n",
2499 dysymtab->tocoff, dysymtab->ntoc);
2500 fprintf (file,
2501 " module table: offset: %lu number: %lu\n",
2502 dysymtab->modtaboff, dysymtab->nmodtab);
2503 break;
2504 }
2505 default:
2506 fprintf (file, "LC_%d\n", cmd->type);
2507 break;
2508 }
2509 }
2510
2511 return TRUE;
2512}
2513
3af9a47b 2514int
116c20d2
NC
2515bfd_mach_o_core_fetch_environment (bfd *abfd,
2516 unsigned char **rbuf,
2517 unsigned int *rlen)
3af9a47b
NC
2518{
2519 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
2520 unsigned long stackaddr = bfd_mach_o_stack_addr (mdata->header.cputype);
2521 unsigned int i = 0;
2522
2523 for (i = 0; i < mdata->header.ncmds; i++)
2524 {
2525 bfd_mach_o_load_command *cur = &mdata->commands[i];
2526 bfd_mach_o_segment_command *seg = NULL;
2527
2528 if (cur->type != BFD_MACH_O_LC_SEGMENT)
2529 continue;
2530
2531 seg = &cur->command.segment;
2532
2533 if ((seg->vmaddr + seg->vmsize) == stackaddr)
2534 {
2535 unsigned long start = seg->fileoff;
2536 unsigned long end = seg->fileoff + seg->filesize;
2537 unsigned char *buf = bfd_malloc (1024);
2538 unsigned long size = 1024;
2539
2540 for (;;)
2541 {
2542 bfd_size_type nread = 0;
2543 unsigned long offset;
2544 int found_nonnull = 0;
2545
2546 if (size > (end - start))
2547 size = (end - start);
2548
515ef31d
NC
2549 buf = bfd_realloc_or_free (buf, size);
2550 if (buf == NULL)
2551 return -1;
2552
3af9a47b
NC
2553 bfd_seek (abfd, end - size, SEEK_SET);
2554 nread = bfd_bread (buf, size, abfd);
a95a4550 2555
3af9a47b 2556 if (nread != size)
515ef31d
NC
2557 {
2558 free (buf);
2559 return -1;
2560 }
a95a4550 2561
3af9a47b
NC
2562 for (offset = 4; offset <= size; offset += 4)
2563 {
e84d6fca 2564 unsigned long val;
3af9a47b 2565
e84d6fca 2566 val = *((unsigned long *) (buf + size - offset));
3af9a47b
NC
2567 if (! found_nonnull)
2568 {
2569 if (val != 0)
2570 found_nonnull = 1;
2571 }
2572 else if (val == 0x0)
2573 {
e84d6fca
AM
2574 unsigned long bottom;
2575 unsigned long top;
3af9a47b 2576
e84d6fca
AM
2577 bottom = seg->fileoff + seg->filesize - offset;
2578 top = seg->fileoff + seg->filesize - 4;
3af9a47b
NC
2579 *rbuf = bfd_malloc (top - bottom);
2580 *rlen = top - bottom;
2581
2582 memcpy (*rbuf, buf + size - *rlen, *rlen);
515ef31d 2583 free (buf);
3af9a47b
NC
2584 return 0;
2585 }
2586 }
2587
2588 if (size == (end - start))
2589 break;
2590
2591 size *= 2;
2592 }
515ef31d
NC
2593
2594 free (buf);
3af9a47b
NC
2595 }
2596 }
2597
2598 return -1;
2599}
2600
2601char *
116c20d2 2602bfd_mach_o_core_file_failing_command (bfd *abfd)
3af9a47b
NC
2603{
2604 unsigned char *buf = NULL;
2605 unsigned int len = 0;
2606 int ret = -1;
2607
2608 ret = bfd_mach_o_core_fetch_environment (abfd, &buf, &len);
2609 if (ret < 0)
2610 return NULL;
2611
f075ee0c 2612 return (char *) buf;
3af9a47b
NC
2613}
2614
2615int
116c20d2 2616bfd_mach_o_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
3af9a47b
NC
2617{
2618 return 0;
2619}
2620
116c20d2
NC
2621#define TARGET_NAME mach_o_be_vec
2622#define TARGET_STRING "mach-o-be"
2623#define TARGET_BIG_ENDIAN 1
2624#define TARGET_ARCHIVE 0
3af9a47b
NC
2625
2626#include "mach-o-target.c"
2627
2628#undef TARGET_NAME
2629#undef TARGET_STRING
2630#undef TARGET_BIG_ENDIAN
2631#undef TARGET_ARCHIVE
2632
116c20d2
NC
2633#define TARGET_NAME mach_o_le_vec
2634#define TARGET_STRING "mach-o-le"
2635#define TARGET_BIG_ENDIAN 0
2636#define TARGET_ARCHIVE 0
3af9a47b
NC
2637
2638#include "mach-o-target.c"
2639
2640#undef TARGET_NAME
2641#undef TARGET_STRING
2642#undef TARGET_BIG_ENDIAN
2643#undef TARGET_ARCHIVE
2644
116c20d2
NC
2645#define TARGET_NAME mach_o_fat_vec
2646#define TARGET_STRING "mach-o-fat"
2647#define TARGET_BIG_ENDIAN 1
2648#define TARGET_ARCHIVE 1
3af9a47b
NC
2649
2650#include "mach-o-target.c"
2651
2652#undef TARGET_NAME
2653#undef TARGET_STRING
2654#undef TARGET_BIG_ENDIAN
2655#undef TARGET_ARCHIVE
This page took 0.46926 seconds and 4 git commands to generate.