* coffcode.h (coff_write_object_contents): Always initialise
[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);
799 else
800 sprintf (sname, "%s.%s.%s", prefix, section->segname, section->sectname);
801
802 if (section->flags & BFD_MACH_O_S_ATTR_DEBUG)
803 flags = SEC_HAS_CONTENTS | SEC_DEBUGGING;
804 else
805 {
806 flags = SEC_ALLOC;
807 if ((section->flags & BFD_MACH_O_SECTION_TYPE_MASK)
808 != BFD_MACH_O_S_ZEROFILL)
809 {
810 flags |= SEC_HAS_CONTENTS | SEC_LOAD;
811 if (prot & BFD_MACH_O_PROT_EXECUTE)
812 flags |= SEC_CODE;
813 if (prot & BFD_MACH_O_PROT_WRITE)
814 flags |= SEC_DATA;
815 else if (prot & BFD_MACH_O_PROT_READ)
816 flags |= SEC_READONLY;
817 }
818 }
117ed4f8 819 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, flags);
3af9a47b
NC
820 if (bfdsec == NULL)
821 return NULL;
a95a4550 822
3af9a47b
NC
823 bfdsec->vma = section->addr;
824 bfdsec->lma = section->addr;
eea6121a 825 bfdsec->size = section->size;
3af9a47b
NC
826 bfdsec->filepos = section->offset;
827 bfdsec->alignment_power = section->align;
1e8a024a 828 bfdsec->segment_mark = 0;
3af9a47b 829
3af9a47b
NC
830 return bfdsec;
831}
832
833static int
1e8a024a
TG
834bfd_mach_o_scan_read_section_32 (bfd *abfd,
835 bfd_mach_o_section *section,
15e1c58a
TG
836 bfd_vma offset,
837 unsigned long prot)
3af9a47b
NC
838{
839 unsigned char buf[68];
840
841 bfd_seek (abfd, offset, SEEK_SET);
842 if (bfd_bread ((PTR) buf, 68, abfd) != 68)
843 return -1;
a95a4550 844
3af9a47b
NC
845 memcpy (section->sectname, buf, 16);
846 section->sectname[16] = '\0';
847 memcpy (section->segname, buf + 16, 16);
848 section->segname[16] = '\0';
849 section->addr = bfd_h_get_32 (abfd, buf + 32);
850 section->size = bfd_h_get_32 (abfd, buf + 36);
851 section->offset = bfd_h_get_32 (abfd, buf + 40);
852 section->align = bfd_h_get_32 (abfd, buf + 44);
853 section->reloff = bfd_h_get_32 (abfd, buf + 48);
854 section->nreloc = bfd_h_get_32 (abfd, buf + 52);
855 section->flags = bfd_h_get_32 (abfd, buf + 56);
856 section->reserved1 = bfd_h_get_32 (abfd, buf + 60);
857 section->reserved2 = bfd_h_get_32 (abfd, buf + 64);
1e8a024a 858 section->reserved3 = 0;
15e1c58a 859 section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section, prot);
1e8a024a
TG
860
861 if (section->bfdsection == NULL)
862 return -1;
863
864 return 0;
865}
866
867static int
868bfd_mach_o_scan_read_section_64 (bfd *abfd,
869 bfd_mach_o_section *section,
15e1c58a
TG
870 bfd_vma offset,
871 unsigned long prot)
1e8a024a
TG
872{
873 unsigned char buf[80];
874
875 bfd_seek (abfd, offset, SEEK_SET);
876 if (bfd_bread ((PTR) buf, 80, abfd) != 80)
877 return -1;
878
879 memcpy (section->sectname, buf, 16);
880 section->sectname[16] = '\0';
881 memcpy (section->segname, buf + 16, 16);
882 section->segname[16] = '\0';
883 section->addr = bfd_h_get_64 (abfd, buf + 32);
884 section->size = bfd_h_get_64 (abfd, buf + 40);
885 section->offset = bfd_h_get_32 (abfd, buf + 48);
886 section->align = bfd_h_get_32 (abfd, buf + 52);
887 section->reloff = bfd_h_get_32 (abfd, buf + 56);
888 section->nreloc = bfd_h_get_32 (abfd, buf + 60);
889 section->flags = bfd_h_get_32 (abfd, buf + 64);
890 section->reserved1 = bfd_h_get_32 (abfd, buf + 68);
891 section->reserved2 = bfd_h_get_32 (abfd, buf + 72);
892 section->reserved3 = bfd_h_get_32 (abfd, buf + 76);
15e1c58a 893 section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section, prot);
3af9a47b
NC
894
895 if (section->bfdsection == NULL)
896 return -1;
897
898 return 0;
899}
900
1e8a024a
TG
901static int
902bfd_mach_o_scan_read_section (bfd *abfd,
903 bfd_mach_o_section *section,
904 bfd_vma offset,
15e1c58a 905 unsigned long prot,
1e8a024a
TG
906 unsigned int wide)
907{
908 if (wide)
15e1c58a 909 return bfd_mach_o_scan_read_section_64 (abfd, section, offset, prot);
1e8a024a 910 else
15e1c58a 911 return bfd_mach_o_scan_read_section_32 (abfd, section, offset, prot);
1e8a024a
TG
912}
913
3af9a47b 914int
116c20d2
NC
915bfd_mach_o_scan_read_symtab_symbol (bfd *abfd,
916 bfd_mach_o_symtab_command *sym,
917 asymbol *s,
918 unsigned long i)
3af9a47b
NC
919{
920 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
1e8a024a
TG
921 unsigned int wide = (mdata->header.version == 2);
922 unsigned int symwidth = wide ? 16 : 12;
923 bfd_vma symoff = sym->symoff + (i * symwidth);
924 unsigned char buf[16];
3af9a47b
NC
925 unsigned char type = -1;
926 unsigned char section = -1;
927 short desc = -1;
1e8a024a 928 symvalue value = -1;
3af9a47b
NC
929 unsigned long stroff = -1;
930 unsigned int symtype = -1;
931
932 BFD_ASSERT (sym->strtab != NULL);
933
934 bfd_seek (abfd, symoff, SEEK_SET);
1e8a024a 935 if (bfd_bread ((PTR) buf, symwidth, abfd) != symwidth)
3af9a47b
NC
936 {
937 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: unable to read %d bytes at %lu\n",
1e8a024a 938 symwidth, (unsigned long) symoff);
3af9a47b
NC
939 return -1;
940 }
941
942 stroff = bfd_h_get_32 (abfd, buf);
943 type = bfd_h_get_8 (abfd, buf + 4);
944 symtype = (type & 0x0e);
15e1c58a 945 section = bfd_h_get_8 (abfd, buf + 5);
3af9a47b 946 desc = bfd_h_get_16 (abfd, buf + 6);
1e8a024a
TG
947 if (wide)
948 value = bfd_h_get_64 (abfd, buf + 8);
949 else
950 value = bfd_h_get_32 (abfd, buf + 8);
3af9a47b
NC
951
952 if (stroff >= sym->strsize)
953 {
954 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: symbol name out of range (%lu >= %lu)\n",
955 (unsigned long) stroff, (unsigned long) sym->strsize);
a95a4550 956 return -1;
3af9a47b
NC
957 }
958
959 s->the_bfd = abfd;
960 s->name = sym->strtab + stroff;
961 s->value = value;
962 s->udata.i = (type << 24) | (section << 16) | desc;
963 s->flags = 0x0;
964
965 if (type & BFD_MACH_O_N_STAB)
966 {
967 s->flags |= BSF_DEBUGGING;
968 s->section = bfd_und_section_ptr;
15e1c58a
TG
969 switch (type)
970 {
971 case N_FUN:
972 case N_STSYM:
973 case N_LCSYM:
974 case N_BNSYM:
975 case N_SLINE:
976 case N_ENSYM:
977 case N_ECOMM:
978 case N_ECOML:
979 case N_GSYM:
980 if ((section > 0) && (section <= mdata->nsects))
981 {
982 s->section = mdata->sections[section - 1]->bfdsection;
983 s->value = s->value - mdata->sections[section - 1]->addr;
984 }
985 break;
986 }
3af9a47b
NC
987 }
988 else
989 {
990 if (type & BFD_MACH_O_N_PEXT)
15e1c58a
TG
991 s->flags |= BSF_GLOBAL;
992
3af9a47b 993 if (type & BFD_MACH_O_N_EXT)
15e1c58a
TG
994 s->flags |= BSF_GLOBAL;
995
996 if (!(type & (BFD_MACH_O_N_PEXT | BFD_MACH_O_N_EXT)))
997 s->flags |= BSF_LOCAL;
3af9a47b
NC
998
999 switch (symtype)
1000 {
1001 case BFD_MACH_O_N_UNDF:
1002 s->section = bfd_und_section_ptr;
1003 break;
1004 case BFD_MACH_O_N_PBUD:
1005 s->section = bfd_und_section_ptr;
1006 break;
1007 case BFD_MACH_O_N_ABS:
1008 s->section = bfd_abs_section_ptr;
1009 break;
1010 case BFD_MACH_O_N_SECT:
1011 if ((section > 0) && (section <= mdata->nsects))
1012 {
15e1c58a
TG
1013 s->section = mdata->sections[section - 1]->bfdsection;
1014 s->value = s->value - mdata->sections[section - 1]->addr;
3af9a47b
NC
1015 }
1016 else
1017 {
1018 /* Mach-O uses 0 to mean "no section"; not an error. */
1019 if (section != 0)
1020 {
1021 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
a95a4550 1022 "symbol \"%s\" specified invalid section %d (max %lu): setting to undefined\n",
3af9a47b
NC
1023 s->name, section, mdata->nsects);
1024 }
1025 s->section = bfd_und_section_ptr;
1026 }
1027 break;
1028 case BFD_MACH_O_N_INDR:
1029 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
a95a4550 1030 "symbol \"%s\" is unsupported 'indirect' reference: setting to undefined\n",
3af9a47b
NC
1031 s->name);
1032 s->section = bfd_und_section_ptr;
1033 break;
1034 default:
1035 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
a95a4550 1036 "symbol \"%s\" specified invalid type field 0x%x: setting to undefined\n",
3af9a47b
NC
1037 s->name, symtype);
1038 s->section = bfd_und_section_ptr;
1039 break;
1040 }
1041 }
1042
1043 return 0;
1044}
1045
1046int
116c20d2
NC
1047bfd_mach_o_scan_read_symtab_strtab (bfd *abfd,
1048 bfd_mach_o_symtab_command *sym)
3af9a47b
NC
1049{
1050 BFD_ASSERT (sym->strtab == NULL);
1051
1052 if (abfd->flags & BFD_IN_MEMORY)
1053 {
1054 struct bfd_in_memory *b;
1055
1056 b = (struct bfd_in_memory *) abfd->iostream;
1057
1058 if ((sym->stroff + sym->strsize) > b->size)
1059 {
1060 bfd_set_error (bfd_error_file_truncated);
1061 return -1;
1062 }
f075ee0c 1063 sym->strtab = (char *) b->buffer + sym->stroff;
3af9a47b
NC
1064 return 0;
1065 }
1066
1067 sym->strtab = bfd_alloc (abfd, sym->strsize);
1068 if (sym->strtab == NULL)
1069 return -1;
1070
1071 bfd_seek (abfd, sym->stroff, SEEK_SET);
1072 if (bfd_bread ((PTR) sym->strtab, sym->strsize, abfd) != sym->strsize)
1073 {
1074 fprintf (stderr, "bfd_mach_o_scan_read_symtab_strtab: unable to read %lu bytes at %lu\n",
1075 sym->strsize, sym->stroff);
a95a4550 1076 return -1;
3af9a47b
NC
1077 }
1078
1079 return 0;
1080}
1081
a95a4550 1082int
116c20d2
NC
1083bfd_mach_o_scan_read_symtab_symbols (bfd *abfd,
1084 bfd_mach_o_symtab_command *sym)
3af9a47b
NC
1085{
1086 unsigned long i;
1087 int ret;
1088
1089 BFD_ASSERT (sym->symbols == NULL);
1090 sym->symbols = bfd_alloc (abfd, sym->nsyms * sizeof (asymbol));
1091
1092 if (sym->symbols == NULL)
1093 {
1094 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbols: unable to allocate memory for symbols\n");
a95a4550 1095 return -1;
3af9a47b 1096 }
a95a4550 1097
3af9a47b
NC
1098 ret = bfd_mach_o_scan_read_symtab_strtab (abfd, sym);
1099 if (ret != 0)
1100 return ret;
1101
1102 for (i = 0; i < sym->nsyms; i++)
1103 {
1104 ret = bfd_mach_o_scan_read_symtab_symbol (abfd, sym, &sym->symbols[i], i);
1105 if (ret != 0)
1106 return ret;
1107 }
a95a4550 1108
3af9a47b
NC
1109 return 0;
1110}
1111
1112int
116c20d2
NC
1113bfd_mach_o_scan_read_dysymtab_symbol (bfd *abfd,
1114 bfd_mach_o_dysymtab_command *dysym,
1115 bfd_mach_o_symtab_command *sym,
1116 asymbol *s,
1117 unsigned long i)
3af9a47b
NC
1118{
1119 unsigned long isymoff = dysym->indirectsymoff + (i * 4);
1120 unsigned long symindex;
1121 unsigned char buf[4];
1122
1123 BFD_ASSERT (i < dysym->nindirectsyms);
a95a4550 1124
3af9a47b
NC
1125 bfd_seek (abfd, isymoff, SEEK_SET);
1126 if (bfd_bread ((PTR) buf, 4, abfd) != 4)
1127 {
1128 fprintf (stderr, "bfd_mach_o_scan_read_dysymtab_symbol: unable to read %lu bytes at %lu\n",
1129 (unsigned long) 4, isymoff);
1130 return -1;
1131 }
1132 symindex = bfd_h_get_32 (abfd, buf);
a95a4550 1133
3af9a47b
NC
1134 return bfd_mach_o_scan_read_symtab_symbol (abfd, sym, s, symindex);
1135}
1136
1137static const char *
116c20d2 1138bfd_mach_o_i386_flavour_string (unsigned int flavour)
3af9a47b
NC
1139{
1140 switch ((int) flavour)
1141 {
15e1c58a
TG
1142 case BFD_MACH_O_x86_THREAD_STATE32: return "x86_THREAD_STATE32";
1143 case BFD_MACH_O_x86_FLOAT_STATE32: return "x86_FLOAT_STATE32";
1144 case BFD_MACH_O_x86_EXCEPTION_STATE32: return "x86_EXCEPTION_STATE32";
1145 case BFD_MACH_O_x86_THREAD_STATE64: return "x86_THREAD_STATE64";
1146 case BFD_MACH_O_x86_FLOAT_STATE64: return "x86_FLOAT_STATE64";
1147 case BFD_MACH_O_x86_EXCEPTION_STATE64: return "x86_EXCEPTION_STATE64";
1148 case BFD_MACH_O_x86_THREAD_STATE: return "x86_THREAD_STATE";
1149 case BFD_MACH_O_x86_FLOAT_STATE: return "x86_FLOAT_STATE";
1150 case BFD_MACH_O_x86_EXCEPTION_STATE: return "x86_EXCEPTION_STATE";
1151 case BFD_MACH_O_x86_DEBUG_STATE32: return "x86_DEBUG_STATE32";
1152 case BFD_MACH_O_x86_DEBUG_STATE64: return "x86_DEBUG_STATE64";
1153 case BFD_MACH_O_x86_DEBUG_STATE: return "x86_DEBUG_STATE";
1154 case BFD_MACH_O_THREAD_STATE_NONE: return "THREAD_STATE_NONE";
3af9a47b
NC
1155 default: return "UNKNOWN";
1156 }
1157}
1158
1159static const char *
116c20d2 1160bfd_mach_o_ppc_flavour_string (unsigned int flavour)
3af9a47b
NC
1161{
1162 switch ((int) flavour)
1163 {
1164 case BFD_MACH_O_PPC_THREAD_STATE: return "PPC_THREAD_STATE";
1165 case BFD_MACH_O_PPC_FLOAT_STATE: return "PPC_FLOAT_STATE";
1166 case BFD_MACH_O_PPC_EXCEPTION_STATE: return "PPC_EXCEPTION_STATE";
1167 case BFD_MACH_O_PPC_VECTOR_STATE: return "PPC_VECTOR_STATE";
1168 default: return "UNKNOWN";
1169 }
1170}
1171
1172static int
116c20d2
NC
1173bfd_mach_o_scan_read_dylinker (bfd *abfd,
1174 bfd_mach_o_load_command *command)
3af9a47b
NC
1175{
1176 bfd_mach_o_dylinker_command *cmd = &command->command.dylinker;
1177 unsigned char buf[4];
1178 unsigned int nameoff;
1179 asection *bfdsec;
1180 char *sname;
1181 const char *prefix;
1182
1183 BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLINKER)
1184 || (command->type == BFD_MACH_O_LC_LOAD_DYLINKER));
1185
1186 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1187 if (bfd_bread ((PTR) buf, 4, abfd) != 4)
1188 return -1;
1189
1190 nameoff = bfd_h_get_32 (abfd, buf + 0);
1191
1192 cmd->name_offset = command->offset + nameoff;
1193 cmd->name_len = command->len - nameoff;
1194
1195 if (command->type == BFD_MACH_O_LC_LOAD_DYLINKER)
1196 prefix = "LC_LOAD_DYLINKER";
1197 else if (command->type == BFD_MACH_O_LC_ID_DYLINKER)
1198 prefix = "LC_ID_DYLINKER";
1199 else
1200 abort ();
1201
116c20d2 1202 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
1203 if (sname == NULL)
1204 return -1;
1205 strcpy (sname, prefix);
1206
117ed4f8 1207 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
3af9a47b
NC
1208 if (bfdsec == NULL)
1209 return -1;
a95a4550 1210
3af9a47b
NC
1211 bfdsec->vma = 0;
1212 bfdsec->lma = 0;
eea6121a 1213 bfdsec->size = command->len - 8;
3af9a47b
NC
1214 bfdsec->filepos = command->offset + 8;
1215 bfdsec->alignment_power = 0;
3af9a47b
NC
1216
1217 cmd->section = bfdsec;
1218
1219 return 0;
1220}
1221
1222static int
116c20d2 1223bfd_mach_o_scan_read_dylib (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1224{
1225 bfd_mach_o_dylib_command *cmd = &command->command.dylib;
1226 unsigned char buf[16];
1227 unsigned int nameoff;
1228 asection *bfdsec;
1229 char *sname;
1230 const char *prefix;
1231
1232 BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLIB)
1233 || (command->type == BFD_MACH_O_LC_LOAD_DYLIB)
1234 || (command->type == BFD_MACH_O_LC_LOAD_WEAK_DYLIB));
1235
1236 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1237 if (bfd_bread ((PTR) buf, 16, abfd) != 16)
1238 return -1;
1239
1240 nameoff = bfd_h_get_32 (abfd, buf + 0);
1241 cmd->timestamp = bfd_h_get_32 (abfd, buf + 4);
1242 cmd->current_version = bfd_h_get_32 (abfd, buf + 8);
1243 cmd->compatibility_version = bfd_h_get_32 (abfd, buf + 12);
1244
1245 cmd->name_offset = command->offset + nameoff;
1246 cmd->name_len = command->len - nameoff;
1247
1248 if (command->type == BFD_MACH_O_LC_LOAD_DYLIB)
1249 prefix = "LC_LOAD_DYLIB";
1250 else if (command->type == BFD_MACH_O_LC_LOAD_WEAK_DYLIB)
1251 prefix = "LC_LOAD_WEAK_DYLIB";
1252 else if (command->type == BFD_MACH_O_LC_ID_DYLIB)
1253 prefix = "LC_ID_DYLIB";
1254 else
1255 abort ();
1256
116c20d2 1257 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
1258 if (sname == NULL)
1259 return -1;
1260 strcpy (sname, prefix);
1261
117ed4f8 1262 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
3af9a47b
NC
1263 if (bfdsec == NULL)
1264 return -1;
a95a4550 1265
3af9a47b
NC
1266 bfdsec->vma = 0;
1267 bfdsec->lma = 0;
eea6121a 1268 bfdsec->size = command->len - 8;
3af9a47b
NC
1269 bfdsec->filepos = command->offset + 8;
1270 bfdsec->alignment_power = 0;
3af9a47b
NC
1271
1272 cmd->section = bfdsec;
1273
1274 return 0;
1275}
1276
1277static int
116c20d2
NC
1278bfd_mach_o_scan_read_prebound_dylib (bfd *abfd ATTRIBUTE_UNUSED,
1279 bfd_mach_o_load_command *command ATTRIBUTE_UNUSED)
3af9a47b
NC
1280{
1281 /* bfd_mach_o_prebound_dylib_command *cmd = &command->command.prebound_dylib; */
1282
1283 BFD_ASSERT (command->type == BFD_MACH_O_LC_PREBOUND_DYLIB);
1284 return 0;
1285}
1286
1287static int
116c20d2 1288bfd_mach_o_scan_read_thread (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1289{
1290 bfd_mach_o_data_struct *mdata = NULL;
1291 bfd_mach_o_thread_command *cmd = &command->command.thread;
1292 unsigned char buf[8];
1293 bfd_vma offset;
1294 unsigned int nflavours;
1295 unsigned int i;
1296
1297 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
1298 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
1299
1300 BFD_ASSERT (bfd_mach_o_valid (abfd));
1301 mdata = abfd->tdata.mach_o_data;
a95a4550 1302
3af9a47b
NC
1303 offset = 8;
1304 nflavours = 0;
1305 while (offset != command->len)
1306 {
1307 if (offset >= command->len)
1308 return -1;
1309
1310 bfd_seek (abfd, command->offset + offset, SEEK_SET);
1311
1312 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
1313 return -1;
1314
1315 offset += 8 + bfd_h_get_32 (abfd, buf + 4) * 4;
1316 nflavours++;
1317 }
1318
116c20d2 1319 cmd->flavours = bfd_alloc (abfd, nflavours * sizeof (bfd_mach_o_thread_flavour));
3af9a47b
NC
1320 if (cmd->flavours == NULL)
1321 return -1;
1322 cmd->nflavours = nflavours;
1323
1324 offset = 8;
1325 nflavours = 0;
1326 while (offset != command->len)
1327 {
1328 if (offset >= command->len)
1329 return -1;
1330
1331 if (nflavours >= cmd->nflavours)
1332 return -1;
1333
1334 bfd_seek (abfd, command->offset + offset, SEEK_SET);
1335
1336 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
1337 return -1;
1338
1339 cmd->flavours[nflavours].flavour = bfd_h_get_32 (abfd, buf);
1340 cmd->flavours[nflavours].offset = command->offset + offset + 8;
1341 cmd->flavours[nflavours].size = bfd_h_get_32 (abfd, buf + 4) * 4;
1342 offset += cmd->flavours[nflavours].size + 8;
1343 nflavours++;
1344 }
1345
1346 for (i = 0; i < nflavours; i++)
1347 {
1348 asection *bfdsec;
1349 unsigned int snamelen;
1350 char *sname;
1351 const char *flavourstr;
1352 const char *prefix = "LC_THREAD";
a95a4550
AM
1353 unsigned int j = 0;
1354
3af9a47b
NC
1355 switch (mdata->header.cputype)
1356 {
1357 case BFD_MACH_O_CPU_TYPE_POWERPC:
1e8a024a 1358 case BFD_MACH_O_CPU_TYPE_POWERPC_64:
3af9a47b
NC
1359 flavourstr = bfd_mach_o_ppc_flavour_string (cmd->flavours[i].flavour);
1360 break;
1361 case BFD_MACH_O_CPU_TYPE_I386:
1e8a024a 1362 case BFD_MACH_O_CPU_TYPE_X86_64:
3af9a47b
NC
1363 flavourstr = bfd_mach_o_i386_flavour_string (cmd->flavours[i].flavour);
1364 break;
1365 default:
1366 flavourstr = "UNKNOWN_ARCHITECTURE";
1367 break;
1368 }
a95a4550 1369
3af9a47b 1370 snamelen = strlen (prefix) + 1 + 20 + 1 + strlen (flavourstr) + 1;
116c20d2 1371 sname = bfd_alloc (abfd, snamelen);
3af9a47b
NC
1372 if (sname == NULL)
1373 return -1;
1374
1375 for (;;)
1376 {
a95a4550
AM
1377 sprintf (sname, "%s.%s.%u", prefix, flavourstr, j);
1378 if (bfd_get_section_by_name (abfd, sname) == NULL)
3af9a47b 1379 break;
a95a4550 1380 j++;
3af9a47b
NC
1381 }
1382
117ed4f8 1383 bfdsec = bfd_make_section_with_flags (abfd, sname, SEC_HAS_CONTENTS);
a95a4550 1384
3af9a47b
NC
1385 bfdsec->vma = 0;
1386 bfdsec->lma = 0;
eea6121a 1387 bfdsec->size = cmd->flavours[i].size;
3af9a47b
NC
1388 bfdsec->filepos = cmd->flavours[i].offset;
1389 bfdsec->alignment_power = 0x0;
3af9a47b
NC
1390
1391 cmd->section = bfdsec;
1392 }
1393
1394 return 0;
1395}
1396
a95a4550 1397static int
116c20d2 1398bfd_mach_o_scan_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1399{
1400 bfd_mach_o_dysymtab_command *seg = &command->command.dysymtab;
1401 unsigned char buf[72];
1402
1403 BFD_ASSERT (command->type == BFD_MACH_O_LC_DYSYMTAB);
1404
1405 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1406 if (bfd_bread ((PTR) buf, 72, abfd) != 72)
1407 return -1;
1408
1409 seg->ilocalsym = bfd_h_get_32 (abfd, buf + 0);
1410 seg->nlocalsym = bfd_h_get_32 (abfd, buf + 4);
1411 seg->iextdefsym = bfd_h_get_32 (abfd, buf + 8);
1412 seg->nextdefsym = bfd_h_get_32 (abfd, buf + 12);
1413 seg->iundefsym = bfd_h_get_32 (abfd, buf + 16);
1414 seg->nundefsym = bfd_h_get_32 (abfd, buf + 20);
1415 seg->tocoff = bfd_h_get_32 (abfd, buf + 24);
1416 seg->ntoc = bfd_h_get_32 (abfd, buf + 28);
1417 seg->modtaboff = bfd_h_get_32 (abfd, buf + 32);
1418 seg->nmodtab = bfd_h_get_32 (abfd, buf + 36);
1419 seg->extrefsymoff = bfd_h_get_32 (abfd, buf + 40);
1420 seg->nextrefsyms = bfd_h_get_32 (abfd, buf + 44);
1421 seg->indirectsymoff = bfd_h_get_32 (abfd, buf + 48);
1422 seg->nindirectsyms = bfd_h_get_32 (abfd, buf + 52);
1423 seg->extreloff = bfd_h_get_32 (abfd, buf + 56);
1424 seg->nextrel = bfd_h_get_32 (abfd, buf + 60);
1425 seg->locreloff = bfd_h_get_32 (abfd, buf + 64);
1426 seg->nlocrel = bfd_h_get_32 (abfd, buf + 68);
1427
1428 return 0;
1429}
1430
a95a4550 1431static int
116c20d2 1432bfd_mach_o_scan_read_symtab (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1433{
1434 bfd_mach_o_symtab_command *seg = &command->command.symtab;
1435 unsigned char buf[16];
1436 asection *bfdsec;
1437 char *sname;
1438 const char *prefix = "LC_SYMTAB.stabs";
1e8a024a 1439 int nlist_size = (bfd_mach_o_version (abfd) > 1) ? 16 : 12;
3af9a47b
NC
1440
1441 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
1442
1443 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1444 if (bfd_bread ((PTR) buf, 16, abfd) != 16)
1445 return -1;
a95a4550 1446
3af9a47b
NC
1447 seg->symoff = bfd_h_get_32 (abfd, buf);
1448 seg->nsyms = bfd_h_get_32 (abfd, buf + 4);
1449 seg->stroff = bfd_h_get_32 (abfd, buf + 8);
1450 seg->strsize = bfd_h_get_32 (abfd, buf + 12);
1451 seg->symbols = NULL;
1452 seg->strtab = NULL;
1453
116c20d2 1454 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
1455 if (sname == NULL)
1456 return -1;
1457 strcpy (sname, prefix);
1458
117ed4f8 1459 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
3af9a47b
NC
1460 if (bfdsec == NULL)
1461 return -1;
a95a4550 1462
3af9a47b
NC
1463 bfdsec->vma = 0;
1464 bfdsec->lma = 0;
1e8a024a 1465 bfdsec->size = seg->nsyms * nlist_size;
3af9a47b
NC
1466 bfdsec->filepos = seg->symoff;
1467 bfdsec->alignment_power = 0;
3af9a47b
NC
1468
1469 seg->stabs_segment = bfdsec;
1470
15e1c58a
TG
1471 if (seg->nsyms != 0)
1472 abfd->flags |= HAS_SYMS;
1473
3af9a47b 1474 prefix = "LC_SYMTAB.stabstr";
116c20d2 1475 sname = bfd_alloc (abfd, strlen (prefix) + 1);
3af9a47b
NC
1476 if (sname == NULL)
1477 return -1;
1478 strcpy (sname, prefix);
1479
117ed4f8 1480 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
3af9a47b
NC
1481 if (bfdsec == NULL)
1482 return -1;
a95a4550 1483
3af9a47b
NC
1484 bfdsec->vma = 0;
1485 bfdsec->lma = 0;
eea6121a 1486 bfdsec->size = seg->strsize;
3af9a47b
NC
1487 bfdsec->filepos = seg->stroff;
1488 bfdsec->alignment_power = 0;
3af9a47b
NC
1489
1490 seg->stabstr_segment = bfdsec;
1491
1492 return 0;
1493}
1494
15e1c58a
TG
1495static int
1496bfd_mach_o_scan_read_uuid (bfd *abfd, bfd_mach_o_load_command *command)
1497{
1498 bfd_mach_o_uuid_command *cmd = &command->command.uuid;
1499 asection *bfdsec;
1500 char *sname;
1501 static const char prefix[] = "LC_UUID";
1502
1503 BFD_ASSERT (command->type == BFD_MACH_O_LC_UUID);
1504
1505 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1506 if (bfd_bread ((PTR) cmd->uuid, 16, abfd) != 16)
1507 return -1;
1508
1509 sname = bfd_alloc (abfd, strlen (prefix) + 1);
1510 if (sname == NULL)
1511 return -1;
1512 strcpy (sname, prefix);
1513
1514 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
1515 if (bfdsec == NULL)
1516 return -1;
1517
1518 bfdsec->vma = 0;
1519 bfdsec->lma = 0;
1520 bfdsec->size = command->len - 8;
1521 bfdsec->filepos = command->offset + 8;
1522 bfdsec->alignment_power = 0;
1523
1524 cmd->section = bfdsec;
1525
1526 return 0;
1527}
1528
3af9a47b 1529static int
1e8a024a
TG
1530bfd_mach_o_scan_read_segment (bfd *abfd,
1531 bfd_mach_o_load_command *command,
1532 unsigned int wide)
3af9a47b 1533{
1e8a024a 1534 unsigned char buf[64];
3af9a47b
NC
1535 bfd_mach_o_segment_command *seg = &command->command.segment;
1536 unsigned long i;
1537 asection *bfdsec;
1538 char *sname;
1539 const char *prefix = "LC_SEGMENT";
1540 unsigned int snamelen;
a95a4550 1541
1e8a024a
TG
1542 if (wide)
1543 {
1544 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT_64);
3af9a47b 1545
1e8a024a
TG
1546 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1547 if (bfd_bread ((PTR) buf, 64, abfd) != 64)
1548 return -1;
3af9a47b 1549
1e8a024a 1550 memcpy (seg->segname, buf, 16);
15e1c58a 1551 seg->segname[16] = '\0';
1e8a024a
TG
1552
1553 seg->vmaddr = bfd_h_get_64 (abfd, buf + 16);
1554 seg->vmsize = bfd_h_get_64 (abfd, buf + 24);
1555 seg->fileoff = bfd_h_get_64 (abfd, buf + 32);
1556 seg->filesize = bfd_h_get_64 (abfd, buf + 40);
1557 seg->maxprot = bfd_h_get_32 (abfd, buf + 48);
1558 seg->initprot = bfd_h_get_32 (abfd, buf + 52);
1559 seg->nsects = bfd_h_get_32 (abfd, buf + 56);
1560 seg->flags = bfd_h_get_32 (abfd, buf + 60);
1561 }
1562 else
1563 {
1564 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
1565
1566 bfd_seek (abfd, command->offset + 8, SEEK_SET);
1567 if (bfd_bread ((PTR) buf, 48, abfd) != 48)
1568 return -1;
1569
1570 memcpy (seg->segname, buf, 16);
15e1c58a 1571 seg->segname[16] = '\0';
1e8a024a
TG
1572
1573 seg->vmaddr = bfd_h_get_32 (abfd, buf + 16);
1574 seg->vmsize = bfd_h_get_32 (abfd, buf + 20);
1575 seg->fileoff = bfd_h_get_32 (abfd, buf + 24);
1576 seg->filesize = bfd_h_get_32 (abfd, buf + 28);
1577 seg->maxprot = bfd_h_get_32 (abfd, buf + 32);
1578 seg->initprot = bfd_h_get_32 (abfd, buf + 36);
1579 seg->nsects = bfd_h_get_32 (abfd, buf + 40);
1580 seg->flags = bfd_h_get_32 (abfd, buf + 44);
1581 }
3af9a47b
NC
1582
1583 snamelen = strlen (prefix) + 1 + strlen (seg->segname) + 1;
116c20d2 1584 sname = bfd_alloc (abfd, snamelen);
3af9a47b
NC
1585 if (sname == NULL)
1586 return -1;
1587 sprintf (sname, "%s.%s", prefix, seg->segname);
1588
1e8a024a 1589 bfdsec = bfd_make_section_anyway (abfd, sname);
3af9a47b
NC
1590 if (bfdsec == NULL)
1591 return -1;
1592
1593 bfdsec->vma = seg->vmaddr;
1594 bfdsec->lma = seg->vmaddr;
eea6121a 1595 bfdsec->size = seg->filesize;
3af9a47b
NC
1596 bfdsec->filepos = seg->fileoff;
1597 bfdsec->alignment_power = 0x0;
15e1c58a 1598 bfdsec->flags = SEC_HAS_CONTENTS;
1e8a024a 1599 bfdsec->segment_mark = 1;
3af9a47b
NC
1600
1601 seg->segment = bfdsec;
1602
1603 if (seg->nsects != 0)
1604 {
116c20d2 1605 seg->sections = bfd_alloc (abfd, seg->nsects * sizeof (bfd_mach_o_section));
3af9a47b
NC
1606 if (seg->sections == NULL)
1607 return -1;
a95a4550 1608
3af9a47b
NC
1609 for (i = 0; i < seg->nsects; i++)
1610 {
1e8a024a
TG
1611 bfd_vma segoff;
1612 if (wide)
1613 segoff = command->offset + 64 + 8 + (i * 80);
1614 else
1615 segoff = command->offset + 48 + 8 + (i * 68);
3af9a47b 1616
1e8a024a 1617 if (bfd_mach_o_scan_read_section
15e1c58a 1618 (abfd, &seg->sections[i], segoff, seg->initprot, wide) != 0)
3af9a47b 1619 return -1;
a95a4550 1620 }
3af9a47b
NC
1621 }
1622
1623 return 0;
1624}
1625
1e8a024a
TG
1626static int
1627bfd_mach_o_scan_read_segment_32 (bfd *abfd, bfd_mach_o_load_command *command)
1628{
1629 return bfd_mach_o_scan_read_segment (abfd, command, 0);
1630}
1631
1632static int
1633bfd_mach_o_scan_read_segment_64 (bfd *abfd, bfd_mach_o_load_command *command)
1634{
1635 return bfd_mach_o_scan_read_segment (abfd, command, 1);
1636}
1637
3af9a47b 1638static int
116c20d2 1639bfd_mach_o_scan_read_command (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1640{
1641 unsigned char buf[8];
1642
1643 bfd_seek (abfd, command->offset, SEEK_SET);
1644 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
1645 return -1;
1646
1647 command->type = (bfd_h_get_32 (abfd, buf) & ~BFD_MACH_O_LC_REQ_DYLD);
e84d6fca
AM
1648 command->type_required = (bfd_h_get_32 (abfd, buf) & BFD_MACH_O_LC_REQ_DYLD
1649 ? 1 : 0);
3af9a47b
NC
1650 command->len = bfd_h_get_32 (abfd, buf + 4);
1651
1652 switch (command->type)
1653 {
1654 case BFD_MACH_O_LC_SEGMENT:
1e8a024a
TG
1655 if (bfd_mach_o_scan_read_segment_32 (abfd, command) != 0)
1656 return -1;
1657 break;
1658 case BFD_MACH_O_LC_SEGMENT_64:
1659 if (bfd_mach_o_scan_read_segment_64 (abfd, command) != 0)
3af9a47b
NC
1660 return -1;
1661 break;
1662 case BFD_MACH_O_LC_SYMTAB:
1663 if (bfd_mach_o_scan_read_symtab (abfd, command) != 0)
1664 return -1;
1665 break;
1666 case BFD_MACH_O_LC_SYMSEG:
1667 break;
1668 case BFD_MACH_O_LC_THREAD:
1669 case BFD_MACH_O_LC_UNIXTHREAD:
1670 if (bfd_mach_o_scan_read_thread (abfd, command) != 0)
1671 return -1;
1672 break;
1673 case BFD_MACH_O_LC_LOAD_DYLINKER:
1674 case BFD_MACH_O_LC_ID_DYLINKER:
1675 if (bfd_mach_o_scan_read_dylinker (abfd, command) != 0)
1676 return -1;
1677 break;
1678 case BFD_MACH_O_LC_LOAD_DYLIB:
1679 case BFD_MACH_O_LC_ID_DYLIB:
1680 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
1681 if (bfd_mach_o_scan_read_dylib (abfd, command) != 0)
1682 return -1;
1683 break;
1684 case BFD_MACH_O_LC_PREBOUND_DYLIB:
1685 if (bfd_mach_o_scan_read_prebound_dylib (abfd, command) != 0)
1686 return -1;
1687 break;
1688 case BFD_MACH_O_LC_LOADFVMLIB:
1689 case BFD_MACH_O_LC_IDFVMLIB:
1690 case BFD_MACH_O_LC_IDENT:
1691 case BFD_MACH_O_LC_FVMFILE:
1692 case BFD_MACH_O_LC_PREPAGE:
1693 case BFD_MACH_O_LC_ROUTINES:
1694 case BFD_MACH_O_LC_SUB_FRAMEWORK:
1695 break;
1696 case BFD_MACH_O_LC_DYSYMTAB:
1697 if (bfd_mach_o_scan_read_dysymtab (abfd, command) != 0)
1698 return -1;
1699 break;
1700 case BFD_MACH_O_LC_SUB_UMBRELLA:
1701 case BFD_MACH_O_LC_SUB_CLIENT:
1702 case BFD_MACH_O_LC_SUB_LIBRARY:
1703 case BFD_MACH_O_LC_TWOLEVEL_HINTS:
1704 case BFD_MACH_O_LC_PREBIND_CKSUM:
1705 break;
15e1c58a
TG
1706 case BFD_MACH_O_LC_UUID:
1707 if (bfd_mach_o_scan_read_uuid (abfd, command) != 0)
1708 return -1;
1709 break;
1710 case BFD_MACH_O_LC_CODE_SIGNATURE:
1711 break;
3af9a47b
NC
1712 default:
1713 fprintf (stderr, "unable to read unknown load command 0x%lx\n",
1714 (unsigned long) command->type);
1715 break;
1716 }
1717
1718 return 0;
1719}
1720
1721static void
116c20d2 1722bfd_mach_o_flatten_sections (bfd *abfd)
3af9a47b
NC
1723{
1724 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
1725 long csect = 0;
1726 unsigned long i, j;
a95a4550 1727
15e1c58a 1728 /* Count total number of sections. */
3af9a47b
NC
1729 mdata->nsects = 0;
1730
1731 for (i = 0; i < mdata->header.ncmds; i++)
1732 {
1e8a024a
TG
1733 if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT
1734 || mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT_64)
3af9a47b 1735 {
e84d6fca
AM
1736 bfd_mach_o_segment_command *seg;
1737
1738 seg = &mdata->commands[i].command.segment;
3af9a47b
NC
1739 mdata->nsects += seg->nsects;
1740 }
1741 }
1742
15e1c58a 1743 /* Allocate sections array. */
e84d6fca
AM
1744 mdata->sections = bfd_alloc (abfd,
1745 mdata->nsects * sizeof (bfd_mach_o_section *));
15e1c58a
TG
1746
1747 /* Fill the array. */
3af9a47b
NC
1748 csect = 0;
1749
1750 for (i = 0; i < mdata->header.ncmds; i++)
1751 {
1e8a024a
TG
1752 if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT
1753 || mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT_64)
3af9a47b 1754 {
e84d6fca 1755 bfd_mach_o_segment_command *seg;
3af9a47b 1756
e84d6fca 1757 seg = &mdata->commands[i].command.segment;
3af9a47b
NC
1758 BFD_ASSERT (csect + seg->nsects <= mdata->nsects);
1759
1760 for (j = 0; j < seg->nsects; j++)
1761 mdata->sections[csect++] = &seg->sections[j];
1762 }
1763 }
1764}
1765
1766int
116c20d2 1767bfd_mach_o_scan_start_address (bfd *abfd)
3af9a47b
NC
1768{
1769 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
1770 bfd_mach_o_thread_command *cmd = NULL;
1771 unsigned long i;
1772
1773 for (i = 0; i < mdata->header.ncmds; i++)
1774 {
1775 if ((mdata->commands[i].type == BFD_MACH_O_LC_THREAD) ||
1776 (mdata->commands[i].type == BFD_MACH_O_LC_UNIXTHREAD))
1777 {
1778 if (cmd == NULL)
1779 cmd = &mdata->commands[i].command.thread;
1780 else
1781 return 0;
1782 }
1783 }
1784
1785 if (cmd == NULL)
1786 return 0;
1787
1788 for (i = 0; i < cmd->nflavours; i++)
1789 {
a95a4550 1790 if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_I386)
e84d6fca 1791 && (cmd->flavours[i].flavour
15e1c58a 1792 == (unsigned long) BFD_MACH_O_x86_THREAD_STATE32))
3af9a47b
NC
1793 {
1794 unsigned char buf[4];
1795
1796 bfd_seek (abfd, cmd->flavours[i].offset + 40, SEEK_SET);
1797
1798 if (bfd_bread (buf, 4, abfd) != 4)
1799 return -1;
1800
1801 abfd->start_address = bfd_h_get_32 (abfd, buf);
1802 }
a95a4550 1803 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC)
3af9a47b
NC
1804 && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE))
1805 {
1806 unsigned char buf[4];
1807
1808 bfd_seek (abfd, cmd->flavours[i].offset + 0, SEEK_SET);
1809
1810 if (bfd_bread (buf, 4, abfd) != 4)
1811 return -1;
1812
1813 abfd->start_address = bfd_h_get_32 (abfd, buf);
1814 }
1e8a024a
TG
1815 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC_64)
1816 && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE_64))
1817 {
1818 unsigned char buf[8];
1819
1820 bfd_seek (abfd, cmd->flavours[i].offset + 0, SEEK_SET);
1821
1822 if (bfd_bread (buf, 8, abfd) != 8)
1823 return -1;
1824
1825 abfd->start_address = bfd_h_get_64 (abfd, buf);
1826 }
1827 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_X86_64)
1828 && (cmd->flavours[i].flavour == BFD_MACH_O_x86_THREAD_STATE64))
1829 {
1830 unsigned char buf[8];
1831
1832 bfd_seek (abfd, cmd->flavours[i].offset + (16 * 8), SEEK_SET);
1833
1834 if (bfd_bread (buf, 8, abfd) != 8)
1835 return -1;
1836
1837 abfd->start_address = bfd_h_get_64 (abfd, buf);
1838 }
3af9a47b
NC
1839 }
1840
1841 return 0;
1842}
1843
1844int
116c20d2
NC
1845bfd_mach_o_scan (bfd *abfd,
1846 bfd_mach_o_header *header,
1847 bfd_mach_o_data_struct *mdata)
3af9a47b
NC
1848{
1849 unsigned int i;
3af9a47b
NC
1850 enum bfd_architecture cputype;
1851 unsigned long cpusubtype;
1e8a024a
TG
1852 unsigned int hdrsize;
1853
1854 hdrsize = (header->version == 2) ? 32 : 28;
3af9a47b 1855
3af9a47b
NC
1856 mdata->header = *header;
1857 mdata->symbols = NULL;
1858
15e1c58a
TG
1859 abfd->flags = abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS);
1860 switch (header->filetype)
1861 {
1862 case BFD_MACH_O_MH_OBJECT:
1863 abfd->flags |= HAS_RELOC;
1864 break;
1865 case BFD_MACH_O_MH_EXECUTE:
1866 abfd->flags |= EXEC_P;
1867 break;
1868 case BFD_MACH_O_MH_DYLIB:
1869 case BFD_MACH_O_MH_BUNDLE:
1870 abfd->flags |= DYNAMIC;
1871 break;
1872 }
1873
3af9a47b
NC
1874 abfd->tdata.mach_o_data = mdata;
1875
e84d6fca
AM
1876 bfd_mach_o_convert_architecture (header->cputype, header->cpusubtype,
1877 &cputype, &cpusubtype);
3af9a47b
NC
1878 if (cputype == bfd_arch_unknown)
1879 {
1880 fprintf (stderr, "bfd_mach_o_scan: unknown architecture 0x%lx/0x%lx\n",
1881 header->cputype, header->cpusubtype);
1882 return -1;
1883 }
1884
1885 bfd_set_arch_mach (abfd, cputype, cpusubtype);
a95a4550 1886
3af9a47b
NC
1887 if (header->ncmds != 0)
1888 {
116c20d2 1889 mdata->commands = bfd_alloc (abfd, header->ncmds * sizeof (bfd_mach_o_load_command));
3af9a47b
NC
1890 if (mdata->commands == NULL)
1891 return -1;
a95a4550 1892
3af9a47b
NC
1893 for (i = 0; i < header->ncmds; i++)
1894 {
1895 bfd_mach_o_load_command *cur = &mdata->commands[i];
1896
1897 if (i == 0)
1e8a024a 1898 cur->offset = hdrsize;
3af9a47b
NC
1899 else
1900 {
1901 bfd_mach_o_load_command *prev = &mdata->commands[i - 1];
1902 cur->offset = prev->offset + prev->len;
1903 }
1904
1905 if (bfd_mach_o_scan_read_command (abfd, cur) < 0)
1906 return -1;
a95a4550 1907 }
3af9a47b
NC
1908 }
1909
1910 if (bfd_mach_o_scan_start_address (abfd) < 0)
7e3102a7 1911 return -1;
3af9a47b
NC
1912
1913 bfd_mach_o_flatten_sections (abfd);
3af9a47b
NC
1914 return 0;
1915}
1916
b34976b6 1917bfd_boolean
116c20d2 1918bfd_mach_o_mkobject (bfd *abfd)
3af9a47b
NC
1919{
1920 bfd_mach_o_data_struct *mdata = NULL;
1921
116c20d2 1922 mdata = bfd_alloc (abfd, sizeof (bfd_mach_o_data_struct));
3af9a47b 1923 if (mdata == NULL)
b34976b6 1924 return FALSE;
3af9a47b
NC
1925 abfd->tdata.mach_o_data = mdata;
1926
1927 mdata->header.magic = 0;
1928 mdata->header.cputype = 0;
1929 mdata->header.cpusubtype = 0;
1930 mdata->header.filetype = 0;
1931 mdata->header.ncmds = 0;
1932 mdata->header.sizeofcmds = 0;
1933 mdata->header.flags = 0;
1934 mdata->header.byteorder = BFD_ENDIAN_UNKNOWN;
1935 mdata->commands = NULL;
1936 mdata->nsymbols = 0;
1937 mdata->symbols = NULL;
1938 mdata->nsects = 0;
1939 mdata->sections = NULL;
1940 mdata->ibfd = NULL;
1941
b34976b6 1942 return TRUE;
3af9a47b
NC
1943}
1944
1945const bfd_target *
116c20d2 1946bfd_mach_o_object_p (bfd *abfd)
3af9a47b 1947{
e84d6fca 1948 struct bfd_preserve preserve;
3af9a47b
NC
1949 bfd_mach_o_header header;
1950
e84d6fca 1951 preserve.marker = NULL;
3af9a47b 1952 if (bfd_mach_o_read_header (abfd, &header) != 0)
e84d6fca 1953 goto wrong;
3af9a47b 1954
e84d6fca
AM
1955 if (! (header.byteorder == BFD_ENDIAN_BIG
1956 || header.byteorder == BFD_ENDIAN_LITTLE))
3af9a47b 1957 {
e84d6fca 1958 fprintf (stderr, "unknown header byte-order value 0x%lx\n",
0af1713e 1959 (unsigned long) header.byteorder);
e84d6fca 1960 goto wrong;
3af9a47b
NC
1961 }
1962
e84d6fca
AM
1963 if (! ((header.byteorder == BFD_ENDIAN_BIG
1964 && abfd->xvec->byteorder == BFD_ENDIAN_BIG
1965 && abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
1966 || (header.byteorder == BFD_ENDIAN_LITTLE
1967 && abfd->xvec->byteorder == BFD_ENDIAN_LITTLE
1968 && abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)))
1969 goto wrong;
3af9a47b 1970
e84d6fca
AM
1971 preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct));
1972 if (preserve.marker == NULL
1973 || !bfd_preserve_save (abfd, &preserve))
1974 goto fail;
3af9a47b 1975
e84d6fca
AM
1976 if (bfd_mach_o_scan (abfd, &header,
1977 (bfd_mach_o_data_struct *) preserve.marker) != 0)
1978 goto wrong;
a95a4550 1979
e84d6fca 1980 bfd_preserve_finish (abfd, &preserve);
3af9a47b 1981 return abfd->xvec;
e84d6fca
AM
1982
1983 wrong:
1984 bfd_set_error (bfd_error_wrong_format);
1985
1986 fail:
1987 if (preserve.marker != NULL)
1988 bfd_preserve_restore (abfd, &preserve);
1989 return NULL;
3af9a47b
NC
1990}
1991
1992const bfd_target *
116c20d2 1993bfd_mach_o_core_p (bfd *abfd)
3af9a47b 1994{
e84d6fca 1995 struct bfd_preserve preserve;
3af9a47b
NC
1996 bfd_mach_o_header header;
1997
e84d6fca 1998 preserve.marker = NULL;
3af9a47b 1999 if (bfd_mach_o_read_header (abfd, &header) != 0)
e84d6fca 2000 goto wrong;
3af9a47b 2001
e84d6fca
AM
2002 if (! (header.byteorder == BFD_ENDIAN_BIG
2003 || header.byteorder == BFD_ENDIAN_LITTLE))
3af9a47b 2004 {
e84d6fca 2005 fprintf (stderr, "unknown header byte-order value 0x%lx\n",
0af1713e 2006 (unsigned long) header.byteorder);
3af9a47b
NC
2007 abort ();
2008 }
2009
e84d6fca
AM
2010 if (! ((header.byteorder == BFD_ENDIAN_BIG
2011 && abfd->xvec->byteorder == BFD_ENDIAN_BIG
2012 && abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
2013 || (header.byteorder == BFD_ENDIAN_LITTLE
2014 && abfd->xvec->byteorder == BFD_ENDIAN_LITTLE
2015 && abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)))
2016 goto wrong;
3af9a47b
NC
2017
2018 if (header.filetype != BFD_MACH_O_MH_CORE)
e84d6fca 2019 goto wrong;
3af9a47b 2020
e84d6fca
AM
2021 preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct));
2022 if (preserve.marker == NULL
2023 || !bfd_preserve_save (abfd, &preserve))
2024 goto fail;
a95a4550 2025
e84d6fca
AM
2026 if (bfd_mach_o_scan (abfd, &header,
2027 (bfd_mach_o_data_struct *) preserve.marker) != 0)
2028 goto wrong;
2029
2030 bfd_preserve_finish (abfd, &preserve);
3af9a47b 2031 return abfd->xvec;
e84d6fca
AM
2032
2033 wrong:
2034 bfd_set_error (bfd_error_wrong_format);
2035
2036 fail:
2037 if (preserve.marker != NULL)
2038 bfd_preserve_restore (abfd, &preserve);
2039 return NULL;
3af9a47b
NC
2040}
2041
2042typedef struct mach_o_fat_archentry
2043{
2044 unsigned long cputype;
2045 unsigned long cpusubtype;
2046 unsigned long offset;
2047 unsigned long size;
2048 unsigned long align;
3af9a47b
NC
2049} mach_o_fat_archentry;
2050
2051typedef struct mach_o_fat_data_struct
2052{
2053 unsigned long magic;
2054 unsigned long nfat_arch;
2055 mach_o_fat_archentry *archentries;
2056} mach_o_fat_data_struct;
2057
2058const bfd_target *
116c20d2 2059bfd_mach_o_archive_p (bfd *abfd)
3af9a47b 2060{
e84d6fca 2061 mach_o_fat_data_struct *adata = NULL;
3af9a47b
NC
2062 unsigned char buf[20];
2063 unsigned long i;
2064
2065 bfd_seek (abfd, 0, SEEK_SET);
2066 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
e84d6fca 2067 goto error;
3af9a47b 2068
116c20d2 2069 adata = bfd_alloc (abfd, sizeof (mach_o_fat_data_struct));
3af9a47b 2070 if (adata == NULL)
e84d6fca 2071 goto error;
a95a4550 2072
3af9a47b
NC
2073 adata->magic = bfd_getb32 (buf);
2074 adata->nfat_arch = bfd_getb32 (buf + 4);
2075 if (adata->magic != 0xcafebabe)
e84d6fca 2076 goto error;
3af9a47b 2077
116c20d2 2078 adata->archentries =
3af9a47b
NC
2079 bfd_alloc (abfd, adata->nfat_arch * sizeof (mach_o_fat_archentry));
2080 if (adata->archentries == NULL)
e84d6fca 2081 goto error;
3af9a47b
NC
2082
2083 for (i = 0; i < adata->nfat_arch; i++)
2084 {
2085 bfd_seek (abfd, 8 + 20 * i, SEEK_SET);
2086
2087 if (bfd_bread ((PTR) buf, 20, abfd) != 20)
e84d6fca 2088 goto error;
3af9a47b
NC
2089 adata->archentries[i].cputype = bfd_getb32 (buf);
2090 adata->archentries[i].cpusubtype = bfd_getb32 (buf + 4);
2091 adata->archentries[i].offset = bfd_getb32 (buf + 8);
2092 adata->archentries[i].size = bfd_getb32 (buf + 12);
2093 adata->archentries[i].align = bfd_getb32 (buf + 16);
3af9a47b
NC
2094 }
2095
2096 abfd->tdata.mach_o_fat_data = adata;
2097 return abfd->xvec;
e84d6fca
AM
2098
2099 error:
2100 if (adata != NULL)
2101 bfd_release (abfd, adata);
2102 bfd_set_error (bfd_error_wrong_format);
2103 return NULL;
3af9a47b
NC
2104}
2105
2106bfd *
116c20d2 2107bfd_mach_o_openr_next_archived_file (bfd *archive, bfd *prev)
3af9a47b 2108{
e84d6fca 2109 mach_o_fat_data_struct *adata;
3af9a47b
NC
2110 mach_o_fat_archentry *entry = NULL;
2111 unsigned long i;
15e1c58a
TG
2112 bfd *nbfd;
2113 const char *arch_name;
2114 enum bfd_architecture arch_type;
2115 unsigned long arch_subtype;
2116 char *s = NULL;
3af9a47b 2117
e84d6fca 2118 adata = (mach_o_fat_data_struct *) archive->tdata.mach_o_fat_data;
3af9a47b
NC
2119 BFD_ASSERT (adata != NULL);
2120
2121 /* Find index of previous entry. */
2122 if (prev == NULL)
2123 i = 0; /* Start at first one. */
2124 else
2125 {
2126 for (i = 0; i < adata->nfat_arch; i++)
2127 {
15e1c58a 2128 if (adata->archentries[i].offset == prev->origin)
3af9a47b
NC
2129 break;
2130 }
2131
2132 if (i == adata->nfat_arch)
2133 {
2134 /* Not found. */
2135 bfd_set_error (bfd_error_bad_value);
a95a4550 2136 return NULL;
3af9a47b
NC
2137 }
2138 i++; /* Get next entry. */
2139 }
a95a4550 2140
3af9a47b
NC
2141 if (i >= adata->nfat_arch)
2142 {
2143 bfd_set_error (bfd_error_no_more_archived_files);
2144 return NULL;
2145 }
2146
2147 entry = &adata->archentries[i];
15e1c58a
TG
2148 nbfd = _bfd_new_bfd_contained_in (archive);
2149 if (nbfd == NULL)
2150 return NULL;
2151
2152 nbfd->origin = entry->offset;
2153
2154 bfd_mach_o_convert_architecture (entry->cputype, entry->cpusubtype,
2155 &arch_type, &arch_subtype);
2156 arch_name = bfd_printable_arch_mach (arch_type, arch_subtype);
2157 s = bfd_malloc (strlen (arch_name) + 1);
2158 if (s == NULL)
2159 return NULL;
2160 strcpy (s, arch_name);
2161 nbfd->filename = s;
2162 nbfd->iostream = NULL;
3af9a47b 2163
15e1c58a 2164 return nbfd;
3af9a47b
NC
2165}
2166
e84d6fca 2167int
116c20d2
NC
2168bfd_mach_o_lookup_section (bfd *abfd,
2169 asection *section,
2170 bfd_mach_o_load_command **mcommand,
2171 bfd_mach_o_section **msection)
3af9a47b
NC
2172{
2173 struct mach_o_data_struct *md = abfd->tdata.mach_o_data;
2174 unsigned int i, j, num;
2175
2176 bfd_mach_o_load_command *ncmd = NULL;
2177 bfd_mach_o_section *nsect = NULL;
2178
2179 BFD_ASSERT (mcommand != NULL);
2180 BFD_ASSERT (msection != NULL);
2181
2182 num = 0;
2183 for (i = 0; i < md->header.ncmds; i++)
2184 {
2185 struct bfd_mach_o_load_command *cmd = &md->commands[i];
2186 struct bfd_mach_o_segment_command *seg = NULL;
2187
1e8a024a
TG
2188 if (cmd->type != BFD_MACH_O_LC_SEGMENT
2189 || cmd->type != BFD_MACH_O_LC_SEGMENT_64)
3af9a47b
NC
2190 continue;
2191 seg = &cmd->command.segment;
a95a4550 2192
3af9a47b
NC
2193 if (seg->segment == section)
2194 {
2195 if (num == 0)
2196 ncmd = cmd;
2197 num++;
2198 }
2199
2200 for (j = 0; j < seg->nsects; j++)
2201 {
2202 struct bfd_mach_o_section *sect = &seg->sections[j];
2203
2204 if (sect->bfdsection == section)
2205 {
2206 if (num == 0)
2207 nsect = sect;
2208 num++;
2209 }
2210 }
2211 }
a95a4550 2212
3af9a47b
NC
2213 *mcommand = ncmd;
2214 *msection = nsect;
2215 return num;
2216}
2217
2218int
116c20d2
NC
2219bfd_mach_o_lookup_command (bfd *abfd,
2220 bfd_mach_o_load_command_type type,
2221 bfd_mach_o_load_command **mcommand)
3af9a47b
NC
2222{
2223 struct mach_o_data_struct *md = NULL;
2224 bfd_mach_o_load_command *ncmd = NULL;
2225 unsigned int i, num;
2226
2227 md = abfd->tdata.mach_o_data;
2228
2229 BFD_ASSERT (md != NULL);
2230 BFD_ASSERT (mcommand != NULL);
2231
2232 num = 0;
2233 for (i = 0; i < md->header.ncmds; i++)
2234 {
2235 struct bfd_mach_o_load_command *cmd = &md->commands[i];
2236
2237 if (cmd->type != type)
2238 continue;
2239
2240 if (num == 0)
2241 ncmd = cmd;
2242 num++;
2243 }
2244
2245 *mcommand = ncmd;
2246 return num;
2247}
2248
2249unsigned long
116c20d2 2250bfd_mach_o_stack_addr (enum bfd_mach_o_cpu_type type)
3af9a47b
NC
2251{
2252 switch (type)
2253 {
2254 case BFD_MACH_O_CPU_TYPE_MC680x0:
2255 return 0x04000000;
2256 case BFD_MACH_O_CPU_TYPE_MC88000:
2257 return 0xffffe000;
2258 case BFD_MACH_O_CPU_TYPE_POWERPC:
2259 return 0xc0000000;
2260 case BFD_MACH_O_CPU_TYPE_I386:
2261 return 0xc0000000;
2262 case BFD_MACH_O_CPU_TYPE_SPARC:
2263 return 0xf0000000;
2264 case BFD_MACH_O_CPU_TYPE_I860:
2265 return 0;
2266 case BFD_MACH_O_CPU_TYPE_HPPA:
e84d6fca 2267 return 0xc0000000 - 0x04000000;
3af9a47b
NC
2268 default:
2269 return 0;
2270 }
2271}
2272
15e1c58a
TG
2273static bfd_boolean
2274bfd_mach_o_bfd_print_private_bfd_data (bfd *abfd, PTR ptr)
2275{
2276 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
2277 FILE *file = (FILE *) ptr;
2278 unsigned int i, j;
2279 unsigned int sec_nbr = 0;
2280
2281 fprintf (file, _("Segments and Sections:\n"));
2282 fprintf (file, _(" #: Segment name Section name Address\n"));
2283
2284 for (i = 0; i < mdata->header.ncmds; i++)
2285 {
2286 bfd_mach_o_segment_command *seg;
2287
2288 if (mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT
2289 && mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT_64)
2290 continue;
2291
2292 seg = &mdata->commands[i].command.segment;
2293
2294 fprintf (file, "[Segment %-16s ", seg->segname);
2295 fprintf_vma (file, seg->vmaddr);
2296 fprintf (file, "-");
2297 fprintf_vma (file, seg->vmaddr + seg->vmsize - 1);
2298 fputc (' ', file);
2299 fputc (seg->initprot & BFD_MACH_O_PROT_READ ? 'r' : '-', file);
2300 fputc (seg->initprot & BFD_MACH_O_PROT_WRITE ? 'w' : '-', file);
2301 fputc (seg->initprot & BFD_MACH_O_PROT_EXECUTE ? 'x' : '-', file);
2302 fprintf (file, "]\n");
2303 for (j = 0; j < seg->nsects; j++)
2304 {
2305 bfd_mach_o_section *sec = &seg->sections[j];
2306 fprintf (file, "%02u: %-16s %-16s ", ++sec_nbr,
2307 sec->segname, sec->sectname);
2308 fprintf_vma (file, sec->addr);
2309 fprintf (file, " ");
2310 fprintf_vma (file, sec->size);
2311 fprintf (file, " %08lx\n", sec->flags);
2312 }
2313 }
2314
2315 for (i = 0; i < mdata->header.ncmds; i++)
2316 {
2317 bfd_mach_o_load_command *cmd = &mdata->commands[i];
2318
2319 switch (cmd->type)
2320 {
2321 case BFD_MACH_O_LC_SEGMENT:
2322 case BFD_MACH_O_LC_SEGMENT_64:
2323 break;
2324 case BFD_MACH_O_LC_UUID:
2325 {
2326 bfd_mach_o_uuid_command *uuid = &cmd->command.uuid;
2327 unsigned int i;
2328
2329 fprintf (file, "\n"
2330 "UUID:");
2331 for (i = 0; i < sizeof (uuid->uuid); i++)
2332 fprintf (file, " %02x", uuid->uuid[i]);
2333 fputc ('\n', file);
2334 }
2335 break;
2336 case BFD_MACH_O_LC_LOAD_DYLIB:
2337 {
2338 bfd_mach_o_dylib_command *dylib = &cmd->command.dylib;
2339 bfd_byte *data = NULL;
2340
2341 if (! bfd_malloc_and_get_section (abfd, dylib->section, &data))
2342 {
2343 if (data != NULL)
2344 free (data);
2345 break;
2346 }
2347 fprintf (file, "\n"
2348 "LOAD_DYLIB: %s\n",
2349 data + dylib->name_offset - cmd->offset - 8);
2350 fprintf (file, " time stamp: 0x%08lx\n",
2351 dylib->timestamp);
2352 fprintf (file, " current version: 0x%08lx\n",
2353 dylib->current_version);
2354 fprintf (file, " comptibility version: 0x%08lx\n",
2355 dylib->compatibility_version);
2356 free (data);
2357 break;
2358 }
2359 case BFD_MACH_O_LC_LOAD_DYLINKER:
2360 {
2361 bfd_mach_o_dylinker_command *linker = &cmd->command.dylinker;
2362 bfd_byte *data = NULL;
2363
2364 if (! bfd_malloc_and_get_section (abfd, linker->section, &data))
2365 {
2366 if (data != NULL)
2367 free (data);
2368 break;
2369 }
2370 fprintf (file, "\n"
2371 "LOAD_DYLINKER: %s\n",
2372 data + linker->name_offset - cmd->offset - 8);
2373 free (data);
2374 break;
2375 }
2376 case BFD_MACH_O_LC_SYMTAB:
2377 {
2378 bfd_mach_o_symtab_command *symtab = &cmd->command.symtab;
2379 fprintf (file, "\n"
2380 "LC_SYMTAB: nsyms: %lu, strsize: %lu\n",
2381 symtab->nsyms, symtab->strsize);
2382 break;
2383 }
2384 case BFD_MACH_O_LC_DYSYMTAB:
2385 {
2386 bfd_mach_o_dysymtab_command *dysymtab = &cmd->command.dysymtab;
2387 fprintf (file, "\n"
2388 "LC_DYSYMTAB:\n"
2389 " local symbols: index: %lu number: %lu\n",
2390 dysymtab->ilocalsym, dysymtab->nlocalsym);
2391 fprintf (file,
2392 " external symbols: index: %lu number: %lu\n",
2393 dysymtab->iextdefsym, dysymtab->nextdefsym);
2394 fprintf (file,
2395 " undefined symbols: index: %lu number: %lu\n",
2396 dysymtab->iundefsym, dysymtab->nundefsym);
2397 fprintf (file,
2398 " ntoc: offset: %lu number: %lu\n",
2399 dysymtab->tocoff, dysymtab->ntoc);
2400 fprintf (file,
2401 " module table: offset: %lu number: %lu\n",
2402 dysymtab->modtaboff, dysymtab->nmodtab);
2403 break;
2404 }
2405 default:
2406 fprintf (file, "LC_%d\n", cmd->type);
2407 break;
2408 }
2409 }
2410
2411 return TRUE;
2412}
2413
3af9a47b 2414int
116c20d2
NC
2415bfd_mach_o_core_fetch_environment (bfd *abfd,
2416 unsigned char **rbuf,
2417 unsigned int *rlen)
3af9a47b
NC
2418{
2419 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
2420 unsigned long stackaddr = bfd_mach_o_stack_addr (mdata->header.cputype);
2421 unsigned int i = 0;
2422
2423 for (i = 0; i < mdata->header.ncmds; i++)
2424 {
2425 bfd_mach_o_load_command *cur = &mdata->commands[i];
2426 bfd_mach_o_segment_command *seg = NULL;
2427
2428 if (cur->type != BFD_MACH_O_LC_SEGMENT)
2429 continue;
2430
2431 seg = &cur->command.segment;
2432
2433 if ((seg->vmaddr + seg->vmsize) == stackaddr)
2434 {
2435 unsigned long start = seg->fileoff;
2436 unsigned long end = seg->fileoff + seg->filesize;
2437 unsigned char *buf = bfd_malloc (1024);
2438 unsigned long size = 1024;
2439
2440 for (;;)
2441 {
2442 bfd_size_type nread = 0;
2443 unsigned long offset;
2444 int found_nonnull = 0;
2445
2446 if (size > (end - start))
2447 size = (end - start);
2448
515ef31d
NC
2449 buf = bfd_realloc_or_free (buf, size);
2450 if (buf == NULL)
2451 return -1;
2452
3af9a47b
NC
2453 bfd_seek (abfd, end - size, SEEK_SET);
2454 nread = bfd_bread (buf, size, abfd);
a95a4550 2455
3af9a47b 2456 if (nread != size)
515ef31d
NC
2457 {
2458 free (buf);
2459 return -1;
2460 }
a95a4550 2461
3af9a47b
NC
2462 for (offset = 4; offset <= size; offset += 4)
2463 {
e84d6fca 2464 unsigned long val;
3af9a47b 2465
e84d6fca 2466 val = *((unsigned long *) (buf + size - offset));
3af9a47b
NC
2467 if (! found_nonnull)
2468 {
2469 if (val != 0)
2470 found_nonnull = 1;
2471 }
2472 else if (val == 0x0)
2473 {
e84d6fca
AM
2474 unsigned long bottom;
2475 unsigned long top;
3af9a47b 2476
e84d6fca
AM
2477 bottom = seg->fileoff + seg->filesize - offset;
2478 top = seg->fileoff + seg->filesize - 4;
3af9a47b
NC
2479 *rbuf = bfd_malloc (top - bottom);
2480 *rlen = top - bottom;
2481
2482 memcpy (*rbuf, buf + size - *rlen, *rlen);
515ef31d 2483 free (buf);
3af9a47b
NC
2484 return 0;
2485 }
2486 }
2487
2488 if (size == (end - start))
2489 break;
2490
2491 size *= 2;
2492 }
515ef31d
NC
2493
2494 free (buf);
3af9a47b
NC
2495 }
2496 }
2497
2498 return -1;
2499}
2500
2501char *
116c20d2 2502bfd_mach_o_core_file_failing_command (bfd *abfd)
3af9a47b
NC
2503{
2504 unsigned char *buf = NULL;
2505 unsigned int len = 0;
2506 int ret = -1;
2507
2508 ret = bfd_mach_o_core_fetch_environment (abfd, &buf, &len);
2509 if (ret < 0)
2510 return NULL;
2511
f075ee0c 2512 return (char *) buf;
3af9a47b
NC
2513}
2514
2515int
116c20d2 2516bfd_mach_o_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
3af9a47b
NC
2517{
2518 return 0;
2519}
2520
116c20d2
NC
2521#define TARGET_NAME mach_o_be_vec
2522#define TARGET_STRING "mach-o-be"
2523#define TARGET_BIG_ENDIAN 1
2524#define TARGET_ARCHIVE 0
3af9a47b
NC
2525
2526#include "mach-o-target.c"
2527
2528#undef TARGET_NAME
2529#undef TARGET_STRING
2530#undef TARGET_BIG_ENDIAN
2531#undef TARGET_ARCHIVE
2532
116c20d2
NC
2533#define TARGET_NAME mach_o_le_vec
2534#define TARGET_STRING "mach-o-le"
2535#define TARGET_BIG_ENDIAN 0
2536#define TARGET_ARCHIVE 0
3af9a47b
NC
2537
2538#include "mach-o-target.c"
2539
2540#undef TARGET_NAME
2541#undef TARGET_STRING
2542#undef TARGET_BIG_ENDIAN
2543#undef TARGET_ARCHIVE
2544
116c20d2
NC
2545#define TARGET_NAME mach_o_fat_vec
2546#define TARGET_STRING "mach-o-fat"
2547#define TARGET_BIG_ENDIAN 1
2548#define TARGET_ARCHIVE 1
3af9a47b
NC
2549
2550#include "mach-o-target.c"
2551
2552#undef TARGET_NAME
2553#undef TARGET_STRING
2554#undef TARGET_BIG_ENDIAN
2555#undef TARGET_ARCHIVE
This page took 0.444415 seconds and 4 git commands to generate.