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