daily update
[deliverable/binutils-gdb.git] / bfd / mach-o.c
CommitLineData
3af9a47b 1/* Mach-O support for BFD.
154a1ee5 2 Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
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
154a1ee5
TG
30#define bfd_mach_o_object_p bfd_mach_o_gen_object_p
31#define bfd_mach_o_core_p bfd_mach_o_gen_core_p
32#define bfd_mach_o_mkobject bfd_false
116c20d2 33
92bc0e80
TG
34#define FILE_ALIGN(off, algn) \
35 (((off) + ((file_ptr) 1 << (algn)) - 1) & ((file_ptr) -1 << (algn)))
36
046b007d
TG
37static int bfd_mach_o_scan_read_symtab_symbols (bfd *);
38
c2f09c75 39unsigned int
1e8a024a
TG
40bfd_mach_o_version (bfd *abfd)
41{
42 bfd_mach_o_data_struct *mdata = NULL;
43
44 BFD_ASSERT (bfd_mach_o_valid (abfd));
046b007d 45 mdata = bfd_mach_o_get_data (abfd);
1e8a024a
TG
46
47 return mdata->header.version;
48}
49
b34976b6 50bfd_boolean
116c20d2 51bfd_mach_o_valid (bfd *abfd)
3af9a47b
NC
52{
53 if (abfd == NULL || abfd->xvec == NULL)
154a1ee5 54 return FALSE;
3af9a47b 55
154a1ee5
TG
56 if (abfd->xvec->flavour != bfd_target_mach_o_flavour)
57 return FALSE;
3af9a47b 58
046b007d 59 if (bfd_mach_o_get_data (abfd) == NULL)
154a1ee5
TG
60 return FALSE;
61 return TRUE;
62}
63
c2f09c75
TG
64static INLINE bfd_boolean
65mach_o_wide_p (bfd_mach_o_header *header)
66{
67 switch (header->version)
68 {
69 case 1:
70 return FALSE;
71 case 2:
72 return TRUE;
73 default:
74 BFD_FAIL ();
75 return FALSE;
76 }
77}
78
79static INLINE bfd_boolean
80bfd_mach_o_wide_p (bfd *abfd)
81{
046b007d 82 return mach_o_wide_p (&bfd_mach_o_get_data (abfd)->header);
c2f09c75
TG
83}
84
154a1ee5
TG
85/* Tables to translate well known Mach-O segment/section names to bfd
86 names. Use of canonical names (such as .text or .debug_frame) is required
87 by gdb. */
88
89struct mach_o_section_name_xlat
90{
91 const char *bfd_name;
92 const char *mach_o_name;
93};
94
95static const struct mach_o_section_name_xlat dwarf_section_names_xlat[] =
96 {
97 { ".debug_frame", "__debug_frame" },
98 { ".debug_info", "__debug_info" },
99 { ".debug_abbrev", "__debug_abbrev" },
100 { ".debug_aranges", "__debug_aranges" },
101 { ".debug_macinfo", "__debug_macinfo" },
102 { ".debug_line", "__debug_line" },
103 { ".debug_loc", "__debug_loc" },
104 { ".debug_pubnames", "__debug_pubnames" },
105 { ".debug_pubtypes", "__debug_pubtypes" },
106 { ".debug_str", "__debug_str" },
107 { ".debug_ranges", "__debug_ranges" },
108 { NULL, NULL}
109 };
110
111static const struct mach_o_section_name_xlat text_section_names_xlat[] =
112 {
113 { ".text", "__text" },
b32e07d7 114 { ".const", "__const" },
154a1ee5
TG
115 { ".cstring", "__cstring" },
116 { ".eh_frame", "__eh_frame" },
117 { NULL, NULL}
118 };
119
120static const struct mach_o_section_name_xlat data_section_names_xlat[] =
121 {
122 { ".data", "__data" },
123 { ".bss", "__bss" },
124 { NULL, NULL}
125 };
126
127struct mach_o_segment_name_xlat
128{
129 const char *segname;
130 const struct mach_o_section_name_xlat *sections;
131};
132
c2f09c75 133static const struct mach_o_segment_name_xlat segsec_names_xlat[] =
154a1ee5
TG
134 {
135 { "__DWARF", dwarf_section_names_xlat },
136 { "__TEXT", text_section_names_xlat },
137 { "__DATA", data_section_names_xlat },
138 { NULL, NULL }
139 };
140
141
142/* Mach-O to bfd names. */
143
144static char *
145bfd_mach_o_convert_section_name_to_bfd (bfd *abfd, bfd_mach_o_section *section)
146{
147 const struct mach_o_segment_name_xlat *seg;
148 char *res;
149 unsigned int len;
c2f09c75 150 const char *pfx = "";
154a1ee5
TG
151
152 for (seg = segsec_names_xlat; seg->segname; seg++)
153 {
154 if (strcmp (seg->segname, section->segname) == 0)
155 {
156 const struct mach_o_section_name_xlat *sec;
157
158 for (sec = seg->sections; sec->mach_o_name; sec++)
159 {
160 if (strcmp (sec->mach_o_name, section->sectname) == 0)
161 {
162 len = strlen (sec->bfd_name);
163 res = bfd_alloc (abfd, len + 1);
c2f09c75 164
154a1ee5
TG
165 if (res == NULL)
166 return NULL;
167 strcpy (res, sec->bfd_name);
168 return res;
169 }
170 }
171 }
172 }
173
c2f09c75 174 len = strlen (section->segname) + 1
154a1ee5
TG
175 + strlen (section->sectname) + 1;
176
c2f09c75
TG
177 /* Put "LC_SEGMENT." prefix if the segment name is weird (ie doesn't start
178 with an underscore. */
179 if (section->segname[0] != '_')
180 {
181 static const char seg_pfx[] = "LC_SEGMENT.";
182
183 pfx = seg_pfx;
184 len += sizeof (seg_pfx) - 1;
185 }
186
154a1ee5
TG
187 res = bfd_alloc (abfd, len);
188 if (res == NULL)
189 return NULL;
c2f09c75 190 snprintf (res, len, "%s%s.%s", pfx, section->segname, section->sectname);
154a1ee5
TG
191 return res;
192}
193
c2f09c75 194/* Convert a bfd section name to a Mach-O segment + section name. */
154a1ee5
TG
195
196static void
197bfd_mach_o_convert_section_name_to_mach_o (bfd *abfd ATTRIBUTE_UNUSED,
198 asection *sect,
199 bfd_mach_o_section *section)
200{
201 const struct mach_o_segment_name_xlat *seg;
202 const char *name = bfd_get_section_name (abfd, sect);
203 const char *dot;
204 unsigned int len;
205 unsigned int seglen;
206 unsigned int seclen;
207
c2f09c75
TG
208 /* List of well known names. They all start with a dot. */
209 if (name[0] == '.')
210 for (seg = segsec_names_xlat; seg->segname; seg++)
211 {
212 const struct mach_o_section_name_xlat *sec;
213
214 for (sec = seg->sections; sec->mach_o_name; sec++)
215 {
216 if (strcmp (sec->bfd_name, name) == 0)
217 {
218 strcpy (section->segname, seg->segname);
219 strcpy (section->sectname, sec->mach_o_name);
220 return;
221 }
222 }
223 }
154a1ee5
TG
224
225 /* Strip LC_SEGMENT. prefix. */
226 if (strncmp (name, "LC_SEGMENT.", 11) == 0)
227 name += 11;
228
229 /* Find a dot. */
230 dot = strchr (name, '.');
231 len = strlen (name);
232
233 /* Try to split name into segment and section names. */
234 if (dot && dot != name)
235 {
236 seglen = dot - name;
237 seclen = len - (dot + 1 - name);
238
239 if (seglen < 16 && seclen < 16)
240 {
241 memcpy (section->segname, name, seglen);
242 section->segname[seglen] = 0;
243 memcpy (section->sectname, dot + 1, seclen);
244 section->sectname[seclen] = 0;
245 return;
246 }
247 }
248
249 if (len > 16)
250 len = 16;
251 memcpy (section->segname, name, len);
252 section->segname[len] = 0;
253 memcpy (section->sectname, name, len);
254 section->sectname[len] = 0;
3af9a47b
NC
255}
256
257/* Copy any private info we understand from the input symbol
258 to the output symbol. */
259
154a1ee5 260bfd_boolean
116c20d2
NC
261bfd_mach_o_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
262 asymbol *isymbol ATTRIBUTE_UNUSED,
263 bfd *obfd ATTRIBUTE_UNUSED,
264 asymbol *osymbol ATTRIBUTE_UNUSED)
3af9a47b 265{
b34976b6 266 return TRUE;
3af9a47b
NC
267}
268
269/* Copy any private info we understand from the input section
270 to the output section. */
271
154a1ee5 272bfd_boolean
116c20d2
NC
273bfd_mach_o_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
274 asection *isection ATTRIBUTE_UNUSED,
275 bfd *obfd ATTRIBUTE_UNUSED,
276 asection *osection ATTRIBUTE_UNUSED)
3af9a47b 277{
b34976b6 278 return TRUE;
3af9a47b
NC
279}
280
281/* Copy any private info we understand from the input bfd
282 to the output bfd. */
283
154a1ee5 284bfd_boolean
116c20d2 285bfd_mach_o_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
3af9a47b 286{
154a1ee5
TG
287 if (bfd_get_flavour (ibfd) != bfd_target_mach_o_flavour
288 || bfd_get_flavour (obfd) != bfd_target_mach_o_flavour)
289 return TRUE;
290
3af9a47b
NC
291 BFD_ASSERT (bfd_mach_o_valid (ibfd));
292 BFD_ASSERT (bfd_mach_o_valid (obfd));
293
154a1ee5
TG
294 /* FIXME: copy commands. */
295
b34976b6 296 return TRUE;
3af9a47b
NC
297}
298
046b007d 299/* Count the total number of symbols. */
154a1ee5 300
3af9a47b 301static long
116c20d2 302bfd_mach_o_count_symbols (bfd *abfd)
3af9a47b 303{
046b007d 304 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b 305
046b007d
TG
306 if (mdata->symtab == NULL)
307 return 0;
308 return mdata->symtab->nsyms;
3af9a47b
NC
309}
310
154a1ee5 311long
116c20d2 312bfd_mach_o_get_symtab_upper_bound (bfd *abfd)
3af9a47b
NC
313{
314 long nsyms = bfd_mach_o_count_symbols (abfd);
315
3af9a47b
NC
316 return ((nsyms + 1) * sizeof (asymbol *));
317}
318
154a1ee5 319long
116c20d2 320bfd_mach_o_canonicalize_symtab (bfd *abfd, asymbol **alocation)
3af9a47b 321{
046b007d 322 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b 323 long nsyms = bfd_mach_o_count_symbols (abfd);
046b007d
TG
324 bfd_mach_o_symtab_command *sym = mdata->symtab;
325 unsigned long j;
3af9a47b
NC
326
327 if (nsyms < 0)
328 return nsyms;
329
046b007d 330 if (bfd_mach_o_scan_read_symtab_symbols (abfd) != 0)
3af9a47b 331 {
046b007d
TG
332 fprintf (stderr,
333 "bfd_mach_o_canonicalize_symtab: unable to load symbols\n");
334 return 0;
335 }
3af9a47b 336
046b007d 337 BFD_ASSERT (sym->symbols != NULL);
3af9a47b 338
046b007d
TG
339 for (j = 0; j < sym->nsyms; j++)
340 alocation[j] = &sym->symbols[j].symbol;
3af9a47b 341
046b007d 342 alocation[j] = NULL;
a95a4550 343
3af9a47b
NC
344 return nsyms;
345}
346
154a1ee5 347void
116c20d2
NC
348bfd_mach_o_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
349 asymbol *symbol,
350 symbol_info *ret)
3af9a47b
NC
351{
352 bfd_symbol_info (symbol, ret);
353}
354
154a1ee5 355void
116c20d2
NC
356bfd_mach_o_print_symbol (bfd *abfd,
357 PTR afile,
358 asymbol *symbol,
359 bfd_print_symbol_type how)
3af9a47b
NC
360{
361 FILE *file = (FILE *) afile;
15e1c58a 362 const char *name;
92bc0e80 363 bfd_mach_o_asymbol *asym = (bfd_mach_o_asymbol *)symbol;
3af9a47b
NC
364
365 switch (how)
366 {
367 case bfd_print_symbol_name:
368 fprintf (file, "%s", symbol->name);
369 break;
370 default:
371 bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
92bc0e80
TG
372 if (asym->n_type & BFD_MACH_O_N_STAB)
373 name = bfd_get_stab_name (asym->n_type);
15e1c58a 374 else
92bc0e80 375 switch (asym->n_type & BFD_MACH_O_N_TYPE)
15e1c58a
TG
376 {
377 case BFD_MACH_O_N_UNDF:
378 name = "UND";
379 break;
380 case BFD_MACH_O_N_ABS:
381 name = "ABS";
382 break;
383 case BFD_MACH_O_N_INDR:
384 name = "INDR";
385 break;
386 case BFD_MACH_O_N_PBUD:
387 name = "PBUD";
388 break;
389 case BFD_MACH_O_N_SECT:
390 name = "SECT";
391 break;
392 default:
393 name = "???";
394 break;
395 }
396 if (name == NULL)
397 name = "";
92bc0e80
TG
398 fprintf (file, " %02x %-6s %02x %04x",
399 asym->n_type, name, asym->n_sect, asym->n_desc);
400 if ((asym->n_type & BFD_MACH_O_N_STAB) == 0
401 && (asym->n_type & BFD_MACH_O_N_TYPE) == BFD_MACH_O_N_SECT)
15e1c58a
TG
402 fprintf (file, " %-5s", symbol->section->name);
403 fprintf (file, " %s", symbol->name);
3af9a47b
NC
404 }
405}
406
407static void
116c20d2
NC
408bfd_mach_o_convert_architecture (bfd_mach_o_cpu_type mtype,
409 bfd_mach_o_cpu_subtype msubtype ATTRIBUTE_UNUSED,
410 enum bfd_architecture *type,
411 unsigned long *subtype)
3af9a47b
NC
412{
413 *subtype = bfd_arch_unknown;
414
415 switch (mtype)
416 {
417 case BFD_MACH_O_CPU_TYPE_VAX: *type = bfd_arch_vax; break;
418 case BFD_MACH_O_CPU_TYPE_MC680x0: *type = bfd_arch_m68k; break;
1e8a024a
TG
419 case BFD_MACH_O_CPU_TYPE_I386:
420 *type = bfd_arch_i386;
421 *subtype = bfd_mach_i386_i386;
422 break;
423 case BFD_MACH_O_CPU_TYPE_X86_64:
424 *type = bfd_arch_i386;
425 *subtype = bfd_mach_x86_64;
426 break;
3af9a47b
NC
427 case BFD_MACH_O_CPU_TYPE_MIPS: *type = bfd_arch_mips; break;
428 case BFD_MACH_O_CPU_TYPE_MC98000: *type = bfd_arch_m98k; break;
429 case BFD_MACH_O_CPU_TYPE_HPPA: *type = bfd_arch_hppa; break;
430 case BFD_MACH_O_CPU_TYPE_ARM: *type = bfd_arch_arm; break;
431 case BFD_MACH_O_CPU_TYPE_MC88000: *type = bfd_arch_m88k; break;
1e8a024a
TG
432 case BFD_MACH_O_CPU_TYPE_SPARC:
433 *type = bfd_arch_sparc;
434 *subtype = bfd_mach_sparc;
435 break;
3af9a47b
NC
436 case BFD_MACH_O_CPU_TYPE_I860: *type = bfd_arch_i860; break;
437 case BFD_MACH_O_CPU_TYPE_ALPHA: *type = bfd_arch_alpha; break;
1e8a024a
TG
438 case BFD_MACH_O_CPU_TYPE_POWERPC:
439 *type = bfd_arch_powerpc;
c2f09c75 440 *subtype = bfd_mach_ppc;
1e8a024a
TG
441 break;
442 case BFD_MACH_O_CPU_TYPE_POWERPC_64:
443 *type = bfd_arch_powerpc;
c2f09c75 444 *subtype = bfd_mach_ppc64;
1e8a024a 445 break;
3af9a47b 446 default:
1e8a024a
TG
447 *type = bfd_arch_unknown;
448 break;
3af9a47b
NC
449 }
450}
a95a4550 451
154a1ee5 452static bfd_boolean
116c20d2
NC
453bfd_mach_o_write_header (bfd *abfd, bfd_mach_o_header *header)
454{
1e8a024a
TG
455 unsigned char buf[32];
456 unsigned int size;
457
c2f09c75 458 size = mach_o_wide_p (header) ?
154a1ee5 459 BFD_MACH_O_HEADER_64_SIZE : BFD_MACH_O_HEADER_SIZE;
116c20d2
NC
460
461 bfd_h_put_32 (abfd, header->magic, buf + 0);
462 bfd_h_put_32 (abfd, header->cputype, buf + 4);
463 bfd_h_put_32 (abfd, header->cpusubtype, buf + 8);
464 bfd_h_put_32 (abfd, header->filetype, buf + 12);
465 bfd_h_put_32 (abfd, header->ncmds, buf + 16);
466 bfd_h_put_32 (abfd, header->sizeofcmds, buf + 20);
467 bfd_h_put_32 (abfd, header->flags, buf + 24);
468
c2f09c75 469 if (mach_o_wide_p (header))
1e8a024a
TG
470 bfd_h_put_32 (abfd, header->reserved, buf + 28);
471
c2f09c75
TG
472 if (bfd_seek (abfd, 0, SEEK_SET) != 0
473 || bfd_bwrite ((PTR) buf, size, abfd) != size)
154a1ee5 474 return FALSE;
116c20d2 475
154a1ee5 476 return TRUE;
116c20d2
NC
477}
478
479static int
1e8a024a 480bfd_mach_o_scan_write_thread (bfd *abfd, bfd_mach_o_load_command *command)
116c20d2
NC
481{
482 bfd_mach_o_thread_command *cmd = &command->command.thread;
483 unsigned int i;
484 unsigned char buf[8];
92bc0e80 485 unsigned int offset;
116c20d2
NC
486 unsigned int nflavours;
487
488 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
489 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
490
491 offset = 8;
492 nflavours = 0;
493 for (i = 0; i < cmd->nflavours; i++)
494 {
495 BFD_ASSERT ((cmd->flavours[i].size % 4) == 0);
496 BFD_ASSERT (cmd->flavours[i].offset == (command->offset + offset + 8));
497
498 bfd_h_put_32 (abfd, cmd->flavours[i].flavour, buf);
499 bfd_h_put_32 (abfd, (cmd->flavours[i].size / 4), buf + 4);
500
c2f09c75
TG
501 if (bfd_seek (abfd, command->offset + offset, SEEK_SET) != 0
502 || bfd_bwrite ((PTR) buf, 8, abfd) != 8)
116c20d2
NC
503 return -1;
504
505 offset += cmd->flavours[i].size + 8;
506 }
507
508 return 0;
509}
510
92bc0e80
TG
511long
512bfd_mach_o_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
513 asection *asect)
514{
515 return (asect->reloc_count + 1) * sizeof (arelent *);
516}
517
b32e07d7
TG
518static int
519bfd_mach_o_canonicalize_one_reloc (bfd *abfd, char *buf,
520 arelent *res, asymbol **syms)
92bc0e80 521{
046b007d 522 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
92bc0e80 523 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
b32e07d7
TG
524 bfd_mach_o_reloc_info reloc;
525 bfd_vma addr;
526 bfd_vma symnum;
527 asymbol **sym;
528
529 addr = bfd_get_32 (abfd, buf + 0);
530 symnum = bfd_get_32 (abfd, buf + 4);
531
532 if (addr & BFD_MACH_O_SR_SCATTERED)
533 {
534 unsigned int j;
535
536 /* Scattered relocation.
537 Extract section and offset from r_value. */
538 res->sym_ptr_ptr = NULL;
539 res->addend = 0;
540 for (j = 0; j < mdata->nsects; j++)
541 {
542 bfd_mach_o_section *sect = mdata->sections[j];
543 if (symnum >= sect->addr && symnum < sect->addr + sect->size)
544 {
545 res->sym_ptr_ptr = sect->bfdsection->symbol_ptr_ptr;
546 res->addend = symnum - sect->addr;
547 break;
548 }
549 }
550 res->address = BFD_MACH_O_GET_SR_ADDRESS (addr);
551 reloc.r_type = BFD_MACH_O_GET_SR_TYPE (addr);
552 reloc.r_length = BFD_MACH_O_GET_SR_LENGTH (addr);
553 reloc.r_pcrel = addr & BFD_MACH_O_SR_PCREL;
554 reloc.r_scattered = 1;
555 }
556 else
557 {
558 unsigned int num = BFD_MACH_O_GET_R_SYMBOLNUM (symnum);
559 res->addend = 0;
560 res->address = addr;
561 if (symnum & BFD_MACH_O_R_EXTERN)
562 sym = syms + num;
563 else
564 {
565 BFD_ASSERT (num != 0);
566 BFD_ASSERT (num <= mdata->nsects);
567 sym = mdata->sections[num - 1]->bfdsection->symbol_ptr_ptr;
568 }
569 res->sym_ptr_ptr = sym;
570 reloc.r_type = BFD_MACH_O_GET_R_TYPE (symnum);
571 reloc.r_length = BFD_MACH_O_GET_R_LENGTH (symnum);
572 reloc.r_pcrel = (symnum & BFD_MACH_O_R_PCREL) ? 1 : 0;
573 reloc.r_scattered = 0;
574 }
575
576 if (!(*bed->_bfd_mach_o_swap_reloc_in)(res, &reloc))
577 return -1;
578 return 0;
579}
580
581static int
582bfd_mach_o_canonicalize_relocs (bfd *abfd, unsigned long filepos,
583 unsigned long count,
584 arelent *res, asymbol **syms)
585{
92bc0e80 586 unsigned long i;
92bc0e80
TG
587 char *native_relocs;
588 bfd_size_type native_size;
589
92bc0e80 590 /* Allocate and read relocs. */
b32e07d7 591 native_size = count * BFD_MACH_O_RELENT_SIZE;
92bc0e80
TG
592 native_relocs = bfd_malloc (native_size);
593 if (native_relocs == NULL)
594 return -1;
595
b32e07d7 596 if (bfd_seek (abfd, filepos, SEEK_SET) != 0
92bc0e80 597 || bfd_bread (native_relocs, native_size, abfd) != native_size)
b32e07d7
TG
598 goto err;
599
600 for (i = 0; i < count; i++)
92bc0e80 601 {
b32e07d7
TG
602 char *buf = native_relocs + BFD_MACH_O_RELENT_SIZE * i;
603
604 if (bfd_mach_o_canonicalize_one_reloc (abfd, buf, &res[i], syms) < 0)
605 goto err;
92bc0e80 606 }
b32e07d7
TG
607 free (native_relocs);
608 return i;
609 err:
610 free (native_relocs);
611 return -1;
612}
613
614long
615bfd_mach_o_canonicalize_reloc (bfd *abfd, asection *asect,
616 arelent **rels, asymbol **syms)
617{
618 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
619 unsigned long i;
620 arelent *res;
621
622 if (asect->reloc_count == 0)
623 return 0;
624
625 /* No need to go further if we don't know how to read relocs. */
626 if (bed->_bfd_mach_o_swap_reloc_in == NULL)
627 return 0;
92bc0e80
TG
628
629 res = bfd_malloc (asect->reloc_count * sizeof (arelent));
630 if (res == NULL)
b32e07d7
TG
631 return -1;
632
633 if (bfd_mach_o_canonicalize_relocs (abfd, asect->rel_filepos,
634 asect->reloc_count, res, syms) < 0)
92bc0e80 635 {
b32e07d7 636 free (res);
92bc0e80
TG
637 return -1;
638 }
639
640 for (i = 0; i < asect->reloc_count; i++)
b32e07d7
TG
641 rels[i] = &res[i];
642 rels[i] = NULL;
643 asect->relocation = res;
92bc0e80 644
b32e07d7
TG
645 return i;
646}
92bc0e80 647
b32e07d7
TG
648long
649bfd_mach_o_get_dynamic_reloc_upper_bound (bfd *abfd)
650{
651 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
92bc0e80 652
b32e07d7
TG
653 if (mdata->dysymtab == NULL)
654 return 1;
655 return (mdata->dysymtab->nextrel + mdata->dysymtab->nlocrel)
656 * sizeof (arelent *);
657}
92bc0e80 658
b32e07d7
TG
659long
660bfd_mach_o_canonicalize_dynamic_reloc (bfd *abfd, arelent **rels,
661 struct bfd_symbol **syms)
662{
663 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
664 bfd_mach_o_dysymtab_command *dysymtab = mdata->dysymtab;
665 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
666 unsigned long i;
667 arelent *res;
668
669 if (dysymtab == NULL)
670 return 0;
671 if (dysymtab->nextrel == 0 && dysymtab->nlocrel == 0)
672 return 0;
673
674 /* No need to go further if we don't know how to read relocs. */
675 if (bed->_bfd_mach_o_swap_reloc_in == NULL)
676 return 0;
677
678 res = bfd_malloc ((dysymtab->nextrel + dysymtab->nlocrel) * sizeof (arelent));
679 if (res == NULL)
680 return -1;
681
682 if (bfd_mach_o_canonicalize_relocs (abfd, dysymtab->extreloff,
683 dysymtab->nextrel, res, syms) < 0)
684 {
685 free (res);
686 return -1;
92bc0e80 687 }
b32e07d7
TG
688
689 if (bfd_mach_o_canonicalize_relocs (abfd, dysymtab->locreloff,
690 dysymtab->nlocrel,
691 res + dysymtab->nextrel, syms) < 0)
692 {
693 free (res);
694 return -1;
695 }
696
697 for (i = 0; i < dysymtab->nextrel + dysymtab->nlocrel; i++)
698 rels[i] = &res[i];
699 rels[i] = NULL;
92bc0e80
TG
700 return i;
701}
702
703static bfd_boolean
704bfd_mach_o_scan_write_relocs (bfd *abfd, bfd_mach_o_section *section)
705{
046b007d 706 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
92bc0e80
TG
707 unsigned int i;
708 arelent **entries;
709 asection *sec;
710 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
711
712 sec = section->bfdsection;
713 if (sec->reloc_count == 0)
714 return TRUE;
715
716 if (bed->_bfd_mach_o_swap_reloc_out == NULL)
717 return TRUE;
718
719 /* Allocate relocation room. */
720 mdata->filelen = FILE_ALIGN(mdata->filelen, 2);
721 section->nreloc = sec->reloc_count;
722 sec->rel_filepos = mdata->filelen;
723 section->reloff = sec->rel_filepos;
724 mdata->filelen += sec->reloc_count * BFD_MACH_O_RELENT_SIZE;
725
726 if (bfd_seek (abfd, section->reloff, SEEK_SET) != 0)
727 return FALSE;
728
729 /* Convert and write. */
730 entries = section->bfdsection->orelocation;
731 for (i = 0; i < section->nreloc; i++)
732 {
733 arelent *rel = entries[i];
734 char buf[8];
735 bfd_mach_o_reloc_info info, *pinfo = &info;
736
737 /* Convert relocation to an intermediate representation. */
738 if (!(*bed->_bfd_mach_o_swap_reloc_out) (rel, pinfo))
739 return FALSE;
740
741 /* Lower the relocation info. */
742 if (pinfo->r_scattered)
743 {
744 unsigned long v;
745
746 v = BFD_MACH_O_SR_SCATTERED
747 | (pinfo->r_pcrel ? BFD_MACH_O_SR_PCREL : 0)
748 | BFD_MACH_O_SET_SR_LENGTH(pinfo->r_length)
749 | BFD_MACH_O_SET_SR_TYPE(pinfo->r_type)
750 | BFD_MACH_O_SET_SR_ADDRESS(pinfo->r_address);
751 bfd_put_32 (abfd, v, buf);
752 bfd_put_32 (abfd, pinfo->r_value, buf + 4);
753 }
754 else
755 {
756 unsigned long v;
757
758 bfd_put_32 (abfd, pinfo->r_address, buf);
759 v = BFD_MACH_O_SET_R_SYMBOLNUM (pinfo->r_value)
760 | (pinfo->r_pcrel ? BFD_MACH_O_R_PCREL : 0)
761 | BFD_MACH_O_SET_R_LENGTH (pinfo->r_length)
762 | (pinfo->r_extern ? BFD_MACH_O_R_EXTERN : 0)
763 | BFD_MACH_O_SET_R_TYPE (pinfo->r_type);
764 bfd_put_32 (abfd, v, buf + 4);
765 }
766
767 if (bfd_bwrite ((PTR) buf, BFD_MACH_O_RELENT_SIZE, abfd)
768 != BFD_MACH_O_RELENT_SIZE)
769 return FALSE;
770 }
771 return TRUE;
772}
773
116c20d2 774static int
92bc0e80 775bfd_mach_o_scan_write_section_32 (bfd *abfd, bfd_mach_o_section *section)
116c20d2 776{
154a1ee5 777 unsigned char buf[BFD_MACH_O_SECTION_SIZE];
116c20d2
NC
778
779 memcpy (buf, section->sectname, 16);
780 memcpy (buf + 16, section->segname, 16);
781 bfd_h_put_32 (abfd, section->addr, buf + 32);
782 bfd_h_put_32 (abfd, section->size, buf + 36);
783 bfd_h_put_32 (abfd, section->offset, buf + 40);
784 bfd_h_put_32 (abfd, section->align, buf + 44);
785 bfd_h_put_32 (abfd, section->reloff, buf + 48);
786 bfd_h_put_32 (abfd, section->nreloc, buf + 52);
787 bfd_h_put_32 (abfd, section->flags, buf + 56);
1e8a024a
TG
788 bfd_h_put_32 (abfd, section->reserved1, buf + 60);
789 bfd_h_put_32 (abfd, section->reserved2, buf + 64);
116c20d2 790
92bc0e80
TG
791 if (bfd_bwrite ((PTR) buf, BFD_MACH_O_SECTION_SIZE, abfd)
792 != BFD_MACH_O_SECTION_SIZE)
116c20d2
NC
793 return -1;
794
795 return 0;
796}
797
798static int
92bc0e80 799bfd_mach_o_scan_write_section_64 (bfd *abfd, bfd_mach_o_section *section)
116c20d2 800{
154a1ee5 801 unsigned char buf[BFD_MACH_O_SECTION_64_SIZE];
116c20d2 802
1e8a024a
TG
803 memcpy (buf, section->sectname, 16);
804 memcpy (buf + 16, section->segname, 16);
805 bfd_h_put_64 (abfd, section->addr, buf + 32);
806 bfd_h_put_64 (abfd, section->size, buf + 40);
807 bfd_h_put_32 (abfd, section->offset, buf + 48);
808 bfd_h_put_32 (abfd, section->align, buf + 52);
809 bfd_h_put_32 (abfd, section->reloff, buf + 56);
810 bfd_h_put_32 (abfd, section->nreloc, buf + 60);
811 bfd_h_put_32 (abfd, section->flags, buf + 64);
812 bfd_h_put_32 (abfd, section->reserved1, buf + 68);
813 bfd_h_put_32 (abfd, section->reserved2, buf + 72);
814 bfd_h_put_32 (abfd, section->reserved3, buf + 76);
116c20d2 815
92bc0e80
TG
816 if (bfd_bwrite ((PTR) buf, BFD_MACH_O_SECTION_64_SIZE, abfd)
817 != BFD_MACH_O_SECTION_64_SIZE)
116c20d2
NC
818 return -1;
819
1e8a024a
TG
820 return 0;
821}
822
823static int
c2f09c75 824bfd_mach_o_scan_write_segment_32 (bfd *abfd, bfd_mach_o_load_command *command)
1e8a024a 825{
c2f09c75 826 unsigned char buf[BFD_MACH_O_LC_SEGMENT_SIZE];
1e8a024a
TG
827 bfd_mach_o_segment_command *seg = &command->command.segment;
828 unsigned long i;
829
c2f09c75
TG
830 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
831
92bc0e80
TG
832 for (i = 0; i < seg->nsects; i++)
833 if (!bfd_mach_o_scan_write_relocs (abfd, &seg->sections[i]))
834 return -1;
c2f09c75 835
92bc0e80 836 memcpy (buf, seg->segname, 16);
c2f09c75
TG
837 bfd_h_put_32 (abfd, seg->vmaddr, buf + 16);
838 bfd_h_put_32 (abfd, seg->vmsize, buf + 20);
839 bfd_h_put_32 (abfd, seg->fileoff, buf + 24);
840 bfd_h_put_32 (abfd, seg->filesize, buf + 28);
841 bfd_h_put_32 (abfd, seg->maxprot, buf + 32);
842 bfd_h_put_32 (abfd, seg->initprot, buf + 36);
843 bfd_h_put_32 (abfd, seg->nsects, buf + 40);
844 bfd_h_put_32 (abfd, seg->flags, buf + 44);
845
846 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
92bc0e80
TG
847 || (bfd_bwrite ((PTR) buf, BFD_MACH_O_LC_SEGMENT_SIZE - 8, abfd)
848 != BFD_MACH_O_LC_SEGMENT_SIZE - 8))
c2f09c75 849 return -1;
1e8a024a 850
116c20d2 851 for (i = 0; i < seg->nsects; i++)
92bc0e80
TG
852 if (bfd_mach_o_scan_write_section_32 (abfd, &seg->sections[i]))
853 return -1;
1e8a024a 854
116c20d2
NC
855 return 0;
856}
857
1e8a024a
TG
858static int
859bfd_mach_o_scan_write_segment_64 (bfd *abfd, bfd_mach_o_load_command *command)
860{
c2f09c75
TG
861 unsigned char buf[BFD_MACH_O_LC_SEGMENT_64_SIZE];
862 bfd_mach_o_segment_command *seg = &command->command.segment;
863 unsigned long i;
864
865 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT_64);
866
92bc0e80
TG
867 for (i = 0; i < seg->nsects; i++)
868 if (!bfd_mach_o_scan_write_relocs (abfd, &seg->sections[i]))
869 return -1;
c2f09c75 870
92bc0e80 871 memcpy (buf, seg->segname, 16);
c2f09c75
TG
872 bfd_h_put_64 (abfd, seg->vmaddr, buf + 16);
873 bfd_h_put_64 (abfd, seg->vmsize, buf + 24);
874 bfd_h_put_64 (abfd, seg->fileoff, buf + 32);
875 bfd_h_put_64 (abfd, seg->filesize, buf + 40);
876 bfd_h_put_32 (abfd, seg->maxprot, buf + 48);
877 bfd_h_put_32 (abfd, seg->initprot, buf + 52);
878 bfd_h_put_32 (abfd, seg->nsects, buf + 56);
879 bfd_h_put_32 (abfd, seg->flags, buf + 60);
880
881 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
92bc0e80
TG
882 || (bfd_bwrite ((PTR) buf, BFD_MACH_O_LC_SEGMENT_64_SIZE - 8, abfd)
883 != BFD_MACH_O_LC_SEGMENT_64_SIZE - 8))
c2f09c75
TG
884 return -1;
885
886 for (i = 0; i < seg->nsects; i++)
92bc0e80
TG
887 if (bfd_mach_o_scan_write_section_64 (abfd, &seg->sections[i]))
888 return -1;
c2f09c75 889
c2f09c75 890 return 0;
1e8a024a
TG
891}
892
c2f09c75
TG
893static bfd_boolean
894bfd_mach_o_scan_write_symtab (bfd *abfd, bfd_mach_o_load_command *command)
116c20d2 895{
046b007d 896 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
116c20d2 897 bfd_mach_o_symtab_command *sym = &command->command.symtab;
c2f09c75 898 unsigned char buf[16];
116c20d2 899 unsigned long i;
c2f09c75 900 unsigned int wide = bfd_mach_o_wide_p (abfd);
046b007d 901 unsigned int symlen = wide ? BFD_MACH_O_NLIST_64_SIZE : BFD_MACH_O_NLIST_SIZE;
c2f09c75
TG
902 struct bfd_strtab_hash *strtab;
903 asymbol **symbols = bfd_get_outsymbols (abfd);
904
905 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
906
907 /* Write the symbols first. */
92bc0e80
TG
908 mdata->filelen = FILE_ALIGN(mdata->filelen, wide ? 3 : 2);
909 sym->symoff = mdata->filelen;
c2f09c75
TG
910 if (bfd_seek (abfd, sym->symoff, SEEK_SET) != 0)
911 return FALSE;
912
913 sym->nsyms = bfd_get_symcount (abfd);
92bc0e80 914 mdata->filelen += sym->nsyms * symlen;
c2f09c75
TG
915
916 strtab = _bfd_stringtab_init ();
917 if (strtab == NULL)
918 return FALSE;
116c20d2
NC
919
920 for (i = 0; i < sym->nsyms; i++)
921 {
c2f09c75 922 unsigned char buf[16];
c2f09c75 923 bfd_size_type index;
92bc0e80 924 bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i];
c2f09c75 925
92bc0e80 926 /* Compute name index. */
c2f09c75 927 /* An index of 0 always means the empty string. */
92bc0e80 928 if (s->symbol.name == 0 || s->symbol.name[0] == '\0')
c2f09c75
TG
929 index = 0;
930 else
931 {
92bc0e80 932 index = _bfd_stringtab_add (strtab, s->symbol.name, TRUE, FALSE);
c2f09c75
TG
933 if (index == (bfd_size_type) -1)
934 goto err;
935 }
c2f09c75 936 bfd_h_put_32 (abfd, index, buf);
92bc0e80
TG
937 bfd_h_put_8 (abfd, s->n_type, buf + 4);
938 bfd_h_put_8 (abfd, s->n_sect, buf + 5);
939 bfd_h_put_16 (abfd, s->n_desc, buf + 6);
c2f09c75 940 if (wide)
92bc0e80 941 bfd_h_put_64 (abfd, s->symbol.section->vma + s->symbol.value, buf + 8);
c2f09c75 942 else
92bc0e80 943 bfd_h_put_32 (abfd, s->symbol.section->vma + s->symbol.value, buf + 8);
116c20d2 944
c2f09c75
TG
945 if (bfd_bwrite ((PTR) buf, symlen, abfd) != symlen)
946 goto err;
116c20d2 947 }
c2f09c75 948 sym->strsize = _bfd_stringtab_size (strtab);
92bc0e80
TG
949 sym->stroff = mdata->filelen;
950 mdata->filelen += sym->strsize;
116c20d2 951
c2f09c75
TG
952 if (_bfd_stringtab_emit (abfd, strtab) != TRUE)
953 goto err;
954 _bfd_stringtab_free (strtab);
116c20d2 955
c2f09c75
TG
956 /* The command. */
957 bfd_h_put_32 (abfd, sym->symoff, buf);
958 bfd_h_put_32 (abfd, sym->nsyms, buf + 4);
959 bfd_h_put_32 (abfd, sym->stroff, buf + 8);
960 bfd_h_put_32 (abfd, sym->strsize, buf + 12);
116c20d2 961
c2f09c75
TG
962 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
963 || bfd_bwrite ((PTR) buf, 16, abfd) != 16)
964 return FALSE;
116c20d2 965
c2f09c75 966 return TRUE;
116c20d2 967
c2f09c75
TG
968 err:
969 _bfd_stringtab_free (strtab);
970 return FALSE;
116c20d2
NC
971}
972
92bc0e80
TG
973/* Process the symbols and generate Mach-O specific fields.
974 Number them. */
975
976static bfd_boolean
977bfd_mach_o_mangle_symbols (bfd *abfd)
978{
979 unsigned long i;
980 asymbol **symbols = bfd_get_outsymbols (abfd);
981
982 for (i = 0; i < bfd_get_symcount (abfd); i++)
983 {
984 bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i];
985
986 if (s->n_type == BFD_MACH_O_N_UNDF && !(s->symbol.flags & BSF_DEBUGGING))
987 {
988 /* As genuine Mach-O symbols type shouldn't be N_UNDF (undefined
989 symbols should be N_UNDEF | N_EXT), we suppose the back-end
990 values haven't been set. */
991 if (s->symbol.section == bfd_abs_section_ptr)
992 s->n_type = BFD_MACH_O_N_ABS;
993 else if (s->symbol.section == bfd_und_section_ptr)
994 {
995 s->n_type = BFD_MACH_O_N_UNDF;
996 if (s->symbol.flags & BSF_WEAK)
997 s->n_desc |= BFD_MACH_O_N_WEAK_REF;
998 }
999 else if (s->symbol.section == bfd_com_section_ptr)
1000 s->n_type = BFD_MACH_O_N_UNDF | BFD_MACH_O_N_EXT;
1001 else
1002 s->n_type = BFD_MACH_O_N_SECT;
1003
1004 if (s->symbol.flags & BSF_GLOBAL)
1005 s->n_type |= BFD_MACH_O_N_EXT;
1006 }
1007
1008 /* Compute section index. */
1009 if (s->symbol.section != bfd_abs_section_ptr
1010 && s->symbol.section != bfd_und_section_ptr
1011 && s->symbol.section != bfd_com_section_ptr)
1012 s->n_sect = s->symbol.section->target_index;
1013
1014 /* Number symbols. */
1015 s->symbol.udata.i = i;
1016 }
1017 return TRUE;
1018}
1019
154a1ee5 1020bfd_boolean
116c20d2 1021bfd_mach_o_write_contents (bfd *abfd)
3af9a47b
NC
1022{
1023 unsigned int i;
046b007d 1024 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b 1025
92bc0e80
TG
1026 if (mdata->header.ncmds == 0)
1027 if (!bfd_mach_o_build_commands (abfd))
1028 return FALSE;
1029
3af9a47b 1030 /* Now write header information. */
c2f09c75
TG
1031 if (mdata->header.filetype == 0)
1032 {
1033 if (abfd->flags & EXEC_P)
1034 mdata->header.filetype = BFD_MACH_O_MH_EXECUTE;
1035 else if (abfd->flags & DYNAMIC)
1036 mdata->header.filetype = BFD_MACH_O_MH_DYLIB;
1037 else
1038 mdata->header.filetype = BFD_MACH_O_MH_OBJECT;
1039 }
154a1ee5 1040 if (!bfd_mach_o_write_header (abfd, &mdata->header))
b34976b6 1041 return FALSE;
3af9a47b 1042
92bc0e80
TG
1043 /* Assign a number to each symbols. */
1044 if (!bfd_mach_o_mangle_symbols (abfd))
1045 return FALSE;
1046
3af9a47b
NC
1047 for (i = 0; i < mdata->header.ncmds; i++)
1048 {
1049 unsigned char buf[8];
1050 bfd_mach_o_load_command *cur = &mdata->commands[i];
1051 unsigned long typeflag;
1052
154a1ee5 1053 typeflag = cur->type | (cur->type_required ? BFD_MACH_O_LC_REQ_DYLD : 0);
3af9a47b
NC
1054
1055 bfd_h_put_32 (abfd, typeflag, buf);
1056 bfd_h_put_32 (abfd, cur->len, buf + 4);
1057
c2f09c75
TG
1058 if (bfd_seek (abfd, cur->offset, SEEK_SET) != 0
1059 || bfd_bwrite ((PTR) buf, 8, abfd) != 8)
b34976b6 1060 return FALSE;
3af9a47b
NC
1061
1062 switch (cur->type)
1063 {
1064 case BFD_MACH_O_LC_SEGMENT:
1e8a024a
TG
1065 if (bfd_mach_o_scan_write_segment_32 (abfd, cur) != 0)
1066 return FALSE;
1067 break;
1068 case BFD_MACH_O_LC_SEGMENT_64:
1069 if (bfd_mach_o_scan_write_segment_64 (abfd, cur) != 0)
b34976b6 1070 return FALSE;
3af9a47b
NC
1071 break;
1072 case BFD_MACH_O_LC_SYMTAB:
c2f09c75 1073 if (!bfd_mach_o_scan_write_symtab (abfd, cur))
b34976b6 1074 return FALSE;
3af9a47b
NC
1075 break;
1076 case BFD_MACH_O_LC_SYMSEG:
1077 break;
1078 case BFD_MACH_O_LC_THREAD:
1079 case BFD_MACH_O_LC_UNIXTHREAD:
1080 if (bfd_mach_o_scan_write_thread (abfd, cur) != 0)
b34976b6 1081 return FALSE;
3af9a47b
NC
1082 break;
1083 case BFD_MACH_O_LC_LOADFVMLIB:
1084 case BFD_MACH_O_LC_IDFVMLIB:
1085 case BFD_MACH_O_LC_IDENT:
1086 case BFD_MACH_O_LC_FVMFILE:
1087 case BFD_MACH_O_LC_PREPAGE:
1088 case BFD_MACH_O_LC_DYSYMTAB:
1089 case BFD_MACH_O_LC_LOAD_DYLIB:
1090 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
1091 case BFD_MACH_O_LC_ID_DYLIB:
046b007d 1092 case BFD_MACH_O_LC_REEXPORT_DYLIB:
3af9a47b
NC
1093 case BFD_MACH_O_LC_LOAD_DYLINKER:
1094 case BFD_MACH_O_LC_ID_DYLINKER:
1095 case BFD_MACH_O_LC_PREBOUND_DYLIB:
1096 case BFD_MACH_O_LC_ROUTINES:
1097 case BFD_MACH_O_LC_SUB_FRAMEWORK:
1098 break;
1099 default:
1100 fprintf (stderr,
1101 "unable to write unknown load command 0x%lx\n",
0af1713e 1102 (unsigned long) cur->type);
b34976b6 1103 return FALSE;
3af9a47b
NC
1104 }
1105 }
1106
b34976b6 1107 return TRUE;
3af9a47b
NC
1108}
1109
154a1ee5
TG
1110/* Build Mach-O load commands from the sections. */
1111
1112bfd_boolean
1113bfd_mach_o_build_commands (bfd *abfd)
1114{
046b007d 1115 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
c2f09c75 1116 unsigned int wide = mach_o_wide_p (&mdata->header);
154a1ee5
TG
1117 bfd_mach_o_segment_command *seg;
1118 bfd_mach_o_section *sections;
1119 asection *sec;
c2f09c75
TG
1120 bfd_mach_o_load_command *cmd;
1121 bfd_mach_o_load_command *symtab_cmd;
1122 int target_index;
154a1ee5
TG
1123
1124 /* Return now if commands are already built. */
1125 if (mdata->header.ncmds)
1126 return FALSE;
1127
1128 /* Very simple version: 1 command (segment) containing all sections. */
c2f09c75
TG
1129 mdata->header.ncmds = 2;
1130 mdata->commands = bfd_alloc (abfd, mdata->header.ncmds
154a1ee5
TG
1131 * sizeof (bfd_mach_o_load_command));
1132 if (mdata->commands == NULL)
1133 return FALSE;
c2f09c75
TG
1134 cmd = &mdata->commands[0];
1135 seg = &cmd->command.segment;
1136
154a1ee5
TG
1137 seg->nsects = bfd_count_sections (abfd);
1138 sections = bfd_alloc (abfd, seg->nsects * sizeof (bfd_mach_o_section));
1139 if (sections == NULL)
1140 return FALSE;
1141 seg->sections = sections;
1142
1143 /* Set segment command. */
1144 if (wide)
1145 {
c2f09c75
TG
1146 cmd->type = BFD_MACH_O_LC_SEGMENT_64;
1147 cmd->offset = BFD_MACH_O_HEADER_64_SIZE;
1148 cmd->len = BFD_MACH_O_LC_SEGMENT_64_SIZE
154a1ee5
TG
1149 + BFD_MACH_O_SECTION_64_SIZE * seg->nsects;
1150 }
1151 else
1152 {
c2f09c75
TG
1153 cmd->type = BFD_MACH_O_LC_SEGMENT;
1154 cmd->offset = BFD_MACH_O_HEADER_SIZE;
1155 cmd->len = BFD_MACH_O_LC_SEGMENT_SIZE
154a1ee5
TG
1156 + BFD_MACH_O_SECTION_SIZE * seg->nsects;
1157 }
c2f09c75
TG
1158 cmd->type_required = FALSE;
1159 mdata->header.sizeofcmds = cmd->len;
92bc0e80 1160 mdata->filelen = cmd->offset + cmd->len;
154a1ee5 1161
c2f09c75
TG
1162 /* Set symtab command. */
1163 symtab_cmd = &mdata->commands[1];
1164
1165 symtab_cmd->type = BFD_MACH_O_LC_SYMTAB;
1166 symtab_cmd->offset = cmd->offset + cmd->len;
1167 symtab_cmd->len = 6 * 4;
1168 symtab_cmd->type_required = FALSE;
1169
1170 mdata->header.sizeofcmds += symtab_cmd->len;
92bc0e80 1171 mdata->filelen += symtab_cmd->len;
c2f09c75
TG
1172
1173 /* Fill segment command. */
154a1ee5
TG
1174 memset (seg->segname, 0, sizeof (seg->segname));
1175 seg->vmaddr = 0;
92bc0e80 1176 seg->fileoff = mdata->filelen;
154a1ee5
TG
1177 seg->filesize = 0;
1178 seg->maxprot = BFD_MACH_O_PROT_READ | BFD_MACH_O_PROT_WRITE
1179 | BFD_MACH_O_PROT_EXECUTE;
1180 seg->initprot = seg->maxprot;
1181 seg->flags = 0;
1182
1183 /* Create Mach-O sections. */
c2f09c75 1184 target_index = 0;
154a1ee5
TG
1185 for (sec = abfd->sections; sec; sec = sec->next)
1186 {
1187 sections->bfdsection = sec;
1188 bfd_mach_o_convert_section_name_to_mach_o (abfd, sec, sections);
1189 sections->addr = bfd_get_section_vma (abfd, sec);
1190 sections->size = bfd_get_section_size (sec);
1191 sections->align = bfd_get_section_alignment (abfd, sec);
c2f09c75 1192
92bc0e80
TG
1193 if (sections->size != 0)
1194 {
1195 mdata->filelen = FILE_ALIGN (mdata->filelen, sections->align);
1196 sections->offset = mdata->filelen;
1197 }
1198 else
1199 sections->offset = 0;
154a1ee5
TG
1200 sections->reloff = 0;
1201 sections->nreloc = 0;
1202 sections->reserved1 = 0;
1203 sections->reserved2 = 0;
1204 sections->reserved3 = 0;
1205
92bc0e80 1206 sec->filepos = sections->offset;
c2f09c75 1207 sec->target_index = ++target_index;
154a1ee5 1208
92bc0e80 1209 mdata->filelen += sections->size;
154a1ee5
TG
1210 sections++;
1211 }
92bc0e80 1212 seg->filesize = mdata->filelen - seg->fileoff;
154a1ee5
TG
1213 seg->vmsize = seg->filesize;
1214
1215 return TRUE;
1216}
1217
1218/* Set the contents of a section. */
1219
1220bfd_boolean
1221bfd_mach_o_set_section_contents (bfd *abfd,
1222 asection *section,
1223 const void * location,
1224 file_ptr offset,
1225 bfd_size_type count)
1226{
1227 file_ptr pos;
1228
1229 /* This must be done first, because bfd_set_section_contents is
1230 going to set output_has_begun to TRUE. */
1231 if (! abfd->output_has_begun && ! bfd_mach_o_build_commands (abfd))
1232 return FALSE;
1233
1234 if (count == 0)
1235 return TRUE;
1236
1237 pos = section->filepos + offset;
1238 if (bfd_seek (abfd, pos, SEEK_SET) != 0
1239 || bfd_bwrite (location, count, abfd) != count)
1240 return FALSE;
1241
1242 return TRUE;
1243}
1244
1245int
116c20d2 1246bfd_mach_o_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
a6b96beb 1247 struct bfd_link_info *info ATTRIBUTE_UNUSED)
3af9a47b
NC
1248{
1249 return 0;
1250}
1251
1252/* Make an empty symbol. This is required only because
1253 bfd_make_section_anyway wants to create a symbol for the section. */
1254
154a1ee5 1255asymbol *
116c20d2 1256bfd_mach_o_make_empty_symbol (bfd *abfd)
3af9a47b
NC
1257{
1258 asymbol *new;
1259
92bc0e80 1260 new = bfd_zalloc (abfd, sizeof (bfd_mach_o_asymbol));
3af9a47b
NC
1261 if (new == NULL)
1262 return new;
1263 new->the_bfd = abfd;
92bc0e80 1264 new->udata.i = 0;
3af9a47b
NC
1265 return new;
1266}
1267
154a1ee5 1268static bfd_boolean
116c20d2 1269bfd_mach_o_read_header (bfd *abfd, bfd_mach_o_header *header)
3af9a47b 1270{
1e8a024a
TG
1271 unsigned char buf[32];
1272 unsigned int size;
edeb6e24 1273 bfd_vma (*get32) (const void *) = NULL;
3af9a47b 1274
1e8a024a 1275 /* Just read the magic number. */
c2f09c75
TG
1276 if (bfd_seek (abfd, 0, SEEK_SET) != 0
1277 || bfd_bread ((PTR) buf, 4, abfd) != 4)
154a1ee5 1278 return FALSE;
3af9a47b 1279
154a1ee5 1280 if (bfd_getb32 (buf) == BFD_MACH_O_MH_MAGIC)
3af9a47b
NC
1281 {
1282 header->byteorder = BFD_ENDIAN_BIG;
154a1ee5 1283 header->magic = BFD_MACH_O_MH_MAGIC;
1e8a024a 1284 header->version = 1;
3af9a47b
NC
1285 get32 = bfd_getb32;
1286 }
154a1ee5 1287 else if (bfd_getl32 (buf) == BFD_MACH_O_MH_MAGIC)
3af9a47b 1288 {
a95a4550 1289 header->byteorder = BFD_ENDIAN_LITTLE;
154a1ee5 1290 header->magic = BFD_MACH_O_MH_MAGIC;
1e8a024a
TG
1291 header->version = 1;
1292 get32 = bfd_getl32;
1293 }
154a1ee5 1294 else if (bfd_getb32 (buf) == BFD_MACH_O_MH_MAGIC_64)
1e8a024a
TG
1295 {
1296 header->byteorder = BFD_ENDIAN_BIG;
154a1ee5 1297 header->magic = BFD_MACH_O_MH_MAGIC_64;
1e8a024a
TG
1298 header->version = 2;
1299 get32 = bfd_getb32;
1300 }
154a1ee5 1301 else if (bfd_getl32 (buf) == BFD_MACH_O_MH_MAGIC_64)
1e8a024a
TG
1302 {
1303 header->byteorder = BFD_ENDIAN_LITTLE;
154a1ee5 1304 header->magic = BFD_MACH_O_MH_MAGIC_64;
1e8a024a 1305 header->version = 2;
3af9a47b
NC
1306 get32 = bfd_getl32;
1307 }
1308 else
1309 {
1310 header->byteorder = BFD_ENDIAN_UNKNOWN;
154a1ee5 1311 return FALSE;
3af9a47b 1312 }
a95a4550 1313
1e8a024a 1314 /* Once the size of the header is known, read the full header. */
c2f09c75 1315 size = mach_o_wide_p (header) ?
154a1ee5 1316 BFD_MACH_O_HEADER_64_SIZE : BFD_MACH_O_HEADER_SIZE;
1e8a024a 1317
c2f09c75
TG
1318 if (bfd_seek (abfd, 0, SEEK_SET) != 0
1319 || bfd_bread ((PTR) buf, size, abfd) != size)
154a1ee5 1320 return FALSE;
1e8a024a 1321
3af9a47b
NC
1322 header->cputype = (*get32) (buf + 4);
1323 header->cpusubtype = (*get32) (buf + 8);
1324 header->filetype = (*get32) (buf + 12);
1325 header->ncmds = (*get32) (buf + 16);
1326 header->sizeofcmds = (*get32) (buf + 20);
1327 header->flags = (*get32) (buf + 24);
1328
c2f09c75 1329 if (mach_o_wide_p (header))
1e8a024a
TG
1330 header->reserved = (*get32) (buf + 28);
1331
154a1ee5 1332 return TRUE;
3af9a47b
NC
1333}
1334
1335static asection *
15e1c58a
TG
1336bfd_mach_o_make_bfd_section (bfd *abfd, bfd_mach_o_section *section,
1337 unsigned long prot)
3af9a47b
NC
1338{
1339 asection *bfdsec;
1340 char *sname;
117ed4f8 1341 flagword flags;
3af9a47b 1342
154a1ee5 1343 sname = bfd_mach_o_convert_section_name_to_bfd (abfd, section);
3af9a47b
NC
1344 if (sname == NULL)
1345 return NULL;
3af9a47b 1346
15e1c58a
TG
1347 if (section->flags & BFD_MACH_O_S_ATTR_DEBUG)
1348 flags = SEC_HAS_CONTENTS | SEC_DEBUGGING;
1349 else
1350 {
1351 flags = SEC_ALLOC;
1352 if ((section->flags & BFD_MACH_O_SECTION_TYPE_MASK)
1353 != BFD_MACH_O_S_ZEROFILL)
1354 {
1355 flags |= SEC_HAS_CONTENTS | SEC_LOAD;
1356 if (prot & BFD_MACH_O_PROT_EXECUTE)
1357 flags |= SEC_CODE;
1358 if (prot & BFD_MACH_O_PROT_WRITE)
1359 flags |= SEC_DATA;
1360 else if (prot & BFD_MACH_O_PROT_READ)
1361 flags |= SEC_READONLY;
1362 }
1363 }
92bc0e80
TG
1364 if (section->nreloc != 0)
1365 flags |= SEC_RELOC;
1366
117ed4f8 1367 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, flags);
3af9a47b
NC
1368 if (bfdsec == NULL)
1369 return NULL;
a95a4550 1370
3af9a47b
NC
1371 bfdsec->vma = section->addr;
1372 bfdsec->lma = section->addr;
eea6121a 1373 bfdsec->size = section->size;
3af9a47b
NC
1374 bfdsec->filepos = section->offset;
1375 bfdsec->alignment_power = section->align;
1e8a024a 1376 bfdsec->segment_mark = 0;
92bc0e80
TG
1377 bfdsec->reloc_count = section->nreloc;
1378 bfdsec->rel_filepos = section->reloff;
3af9a47b 1379
3af9a47b
NC
1380 return bfdsec;
1381}
1382
1383static int
1e8a024a
TG
1384bfd_mach_o_scan_read_section_32 (bfd *abfd,
1385 bfd_mach_o_section *section,
92bc0e80 1386 unsigned int offset,
15e1c58a 1387 unsigned long prot)
3af9a47b 1388{
154a1ee5 1389 unsigned char buf[BFD_MACH_O_SECTION_SIZE];
3af9a47b 1390
c2f09c75
TG
1391 if (bfd_seek (abfd, offset, SEEK_SET) != 0
1392 || (bfd_bread ((PTR) buf, BFD_MACH_O_SECTION_SIZE, abfd)
1393 != BFD_MACH_O_SECTION_SIZE))
3af9a47b 1394 return -1;
a95a4550 1395
3af9a47b
NC
1396 memcpy (section->sectname, buf, 16);
1397 section->sectname[16] = '\0';
1398 memcpy (section->segname, buf + 16, 16);
1399 section->segname[16] = '\0';
1400 section->addr = bfd_h_get_32 (abfd, buf + 32);
1401 section->size = bfd_h_get_32 (abfd, buf + 36);
1402 section->offset = bfd_h_get_32 (abfd, buf + 40);
1403 section->align = bfd_h_get_32 (abfd, buf + 44);
1404 section->reloff = bfd_h_get_32 (abfd, buf + 48);
1405 section->nreloc = bfd_h_get_32 (abfd, buf + 52);
1406 section->flags = bfd_h_get_32 (abfd, buf + 56);
1407 section->reserved1 = bfd_h_get_32 (abfd, buf + 60);
1408 section->reserved2 = bfd_h_get_32 (abfd, buf + 64);
1e8a024a 1409 section->reserved3 = 0;
15e1c58a 1410 section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section, prot);
1e8a024a
TG
1411
1412 if (section->bfdsection == NULL)
1413 return -1;
1414
1415 return 0;
1416}
1417
1418static int
1419bfd_mach_o_scan_read_section_64 (bfd *abfd,
1420 bfd_mach_o_section *section,
92bc0e80 1421 unsigned int offset,
15e1c58a 1422 unsigned long prot)
1e8a024a 1423{
154a1ee5 1424 unsigned char buf[BFD_MACH_O_SECTION_64_SIZE];
1e8a024a 1425
c2f09c75
TG
1426 if (bfd_seek (abfd, offset, SEEK_SET) != 0
1427 || (bfd_bread ((PTR) buf, BFD_MACH_O_SECTION_64_SIZE, abfd)
1428 != BFD_MACH_O_SECTION_64_SIZE))
1e8a024a
TG
1429 return -1;
1430
1431 memcpy (section->sectname, buf, 16);
1432 section->sectname[16] = '\0';
1433 memcpy (section->segname, buf + 16, 16);
1434 section->segname[16] = '\0';
1435 section->addr = bfd_h_get_64 (abfd, buf + 32);
1436 section->size = bfd_h_get_64 (abfd, buf + 40);
1437 section->offset = bfd_h_get_32 (abfd, buf + 48);
1438 section->align = bfd_h_get_32 (abfd, buf + 52);
1439 section->reloff = bfd_h_get_32 (abfd, buf + 56);
1440 section->nreloc = bfd_h_get_32 (abfd, buf + 60);
1441 section->flags = bfd_h_get_32 (abfd, buf + 64);
1442 section->reserved1 = bfd_h_get_32 (abfd, buf + 68);
1443 section->reserved2 = bfd_h_get_32 (abfd, buf + 72);
1444 section->reserved3 = bfd_h_get_32 (abfd, buf + 76);
15e1c58a 1445 section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section, prot);
3af9a47b
NC
1446
1447 if (section->bfdsection == NULL)
1448 return -1;
1449
1450 return 0;
1451}
1452
1e8a024a
TG
1453static int
1454bfd_mach_o_scan_read_section (bfd *abfd,
1455 bfd_mach_o_section *section,
92bc0e80 1456 unsigned int offset,
15e1c58a 1457 unsigned long prot,
1e8a024a
TG
1458 unsigned int wide)
1459{
1460 if (wide)
15e1c58a 1461 return bfd_mach_o_scan_read_section_64 (abfd, section, offset, prot);
1e8a024a 1462 else
15e1c58a 1463 return bfd_mach_o_scan_read_section_32 (abfd, section, offset, prot);
1e8a024a
TG
1464}
1465
046b007d 1466static int
116c20d2
NC
1467bfd_mach_o_scan_read_symtab_symbol (bfd *abfd,
1468 bfd_mach_o_symtab_command *sym,
92bc0e80 1469 bfd_mach_o_asymbol *s,
116c20d2 1470 unsigned long i)
3af9a47b 1471{
046b007d 1472 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
c2f09c75 1473 unsigned int wide = mach_o_wide_p (&mdata->header);
046b007d
TG
1474 unsigned int symwidth =
1475 wide ? BFD_MACH_O_NLIST_64_SIZE : BFD_MACH_O_NLIST_SIZE;
92bc0e80 1476 unsigned int symoff = sym->symoff + (i * symwidth);
1e8a024a 1477 unsigned char buf[16];
3af9a47b
NC
1478 unsigned char type = -1;
1479 unsigned char section = -1;
1480 short desc = -1;
1e8a024a 1481 symvalue value = -1;
3af9a47b
NC
1482 unsigned long stroff = -1;
1483 unsigned int symtype = -1;
1484
1485 BFD_ASSERT (sym->strtab != NULL);
1486
c2f09c75
TG
1487 if (bfd_seek (abfd, symoff, SEEK_SET) != 0
1488 || bfd_bread ((PTR) buf, symwidth, abfd) != symwidth)
3af9a47b
NC
1489 {
1490 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: unable to read %d bytes at %lu\n",
1e8a024a 1491 symwidth, (unsigned long) symoff);
3af9a47b
NC
1492 return -1;
1493 }
1494
1495 stroff = bfd_h_get_32 (abfd, buf);
1496 type = bfd_h_get_8 (abfd, buf + 4);
c2f09c75 1497 symtype = type & BFD_MACH_O_N_TYPE;
15e1c58a 1498 section = bfd_h_get_8 (abfd, buf + 5);
3af9a47b 1499 desc = bfd_h_get_16 (abfd, buf + 6);
1e8a024a
TG
1500 if (wide)
1501 value = bfd_h_get_64 (abfd, buf + 8);
1502 else
1503 value = bfd_h_get_32 (abfd, buf + 8);
3af9a47b
NC
1504
1505 if (stroff >= sym->strsize)
1506 {
1507 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: symbol name out of range (%lu >= %lu)\n",
1508 (unsigned long) stroff, (unsigned long) sym->strsize);
a95a4550 1509 return -1;
3af9a47b
NC
1510 }
1511
92bc0e80
TG
1512 s->symbol.the_bfd = abfd;
1513 s->symbol.name = sym->strtab + stroff;
1514 s->symbol.value = value;
1515 s->symbol.flags = 0x0;
1516 s->symbol.udata.i = 0;
1517 s->n_type = type;
1518 s->n_sect = section;
1519 s->n_desc = desc;
3af9a47b
NC
1520
1521 if (type & BFD_MACH_O_N_STAB)
1522 {
92bc0e80
TG
1523 s->symbol.flags |= BSF_DEBUGGING;
1524 s->symbol.section = bfd_und_section_ptr;
15e1c58a
TG
1525 switch (type)
1526 {
1527 case N_FUN:
1528 case N_STSYM:
1529 case N_LCSYM:
1530 case N_BNSYM:
1531 case N_SLINE:
1532 case N_ENSYM:
1533 case N_ECOMM:
1534 case N_ECOML:
1535 case N_GSYM:
1536 if ((section > 0) && (section <= mdata->nsects))
1537 {
92bc0e80
TG
1538 s->symbol.section = mdata->sections[section - 1]->bfdsection;
1539 s->symbol.value =
1540 s->symbol.value - mdata->sections[section - 1]->addr;
15e1c58a
TG
1541 }
1542 break;
1543 }
3af9a47b
NC
1544 }
1545 else
1546 {
1547 if (type & BFD_MACH_O_N_PEXT)
92bc0e80 1548 s->symbol.flags |= BSF_GLOBAL;
c2f09c75 1549
3af9a47b 1550 if (type & BFD_MACH_O_N_EXT)
92bc0e80 1551 s->symbol.flags |= BSF_GLOBAL;
15e1c58a
TG
1552
1553 if (!(type & (BFD_MACH_O_N_PEXT | BFD_MACH_O_N_EXT)))
92bc0e80 1554 s->symbol.flags |= BSF_LOCAL;
3af9a47b
NC
1555
1556 switch (symtype)
1557 {
1558 case BFD_MACH_O_N_UNDF:
c2f09c75 1559 if (type == (BFD_MACH_O_N_UNDF | BFD_MACH_O_N_EXT)
92bc0e80 1560 && s->symbol.value != 0)
c2f09c75
TG
1561 {
1562 /* A common symbol. */
92bc0e80
TG
1563 s->symbol.section = bfd_com_section_ptr;
1564 s->symbol.flags = BSF_NO_FLAGS;
c2f09c75
TG
1565 }
1566 else
92bc0e80
TG
1567 {
1568 s->symbol.section = bfd_und_section_ptr;
1569 if (s->n_desc & BFD_MACH_O_N_WEAK_REF)
1570 s->symbol.flags |= BSF_WEAK;
1571 }
3af9a47b
NC
1572 break;
1573 case BFD_MACH_O_N_PBUD:
92bc0e80 1574 s->symbol.section = bfd_und_section_ptr;
3af9a47b
NC
1575 break;
1576 case BFD_MACH_O_N_ABS:
92bc0e80 1577 s->symbol.section = bfd_abs_section_ptr;
3af9a47b
NC
1578 break;
1579 case BFD_MACH_O_N_SECT:
1580 if ((section > 0) && (section <= mdata->nsects))
1581 {
92bc0e80
TG
1582 s->symbol.section = mdata->sections[section - 1]->bfdsection;
1583 s->symbol.value =
1584 s->symbol.value - mdata->sections[section - 1]->addr;
3af9a47b
NC
1585 }
1586 else
1587 {
1588 /* Mach-O uses 0 to mean "no section"; not an error. */
1589 if (section != 0)
1590 {
1591 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
a95a4550 1592 "symbol \"%s\" specified invalid section %d (max %lu): setting to undefined\n",
92bc0e80 1593 s->symbol.name, section, mdata->nsects);
3af9a47b 1594 }
92bc0e80 1595 s->symbol.section = bfd_und_section_ptr;
3af9a47b
NC
1596 }
1597 break;
1598 case BFD_MACH_O_N_INDR:
1599 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
a95a4550 1600 "symbol \"%s\" is unsupported 'indirect' reference: setting to undefined\n",
92bc0e80
TG
1601 s->symbol.name);
1602 s->symbol.section = bfd_und_section_ptr;
3af9a47b
NC
1603 break;
1604 default:
1605 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
a95a4550 1606 "symbol \"%s\" specified invalid type field 0x%x: setting to undefined\n",
92bc0e80
TG
1607 s->symbol.name, symtype);
1608 s->symbol.section = bfd_und_section_ptr;
3af9a47b
NC
1609 break;
1610 }
1611 }
1612
1613 return 0;
1614}
1615
046b007d
TG
1616static int
1617bfd_mach_o_scan_read_symtab_strtab (bfd *abfd)
3af9a47b 1618{
046b007d
TG
1619 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
1620 bfd_mach_o_symtab_command *sym = mdata->symtab;
1621
1622 /* Fail if there is no symtab. */
1623 if (sym == NULL)
1624 return -1;
1625
1626 /* Success if already loaded. */
1627 if (sym->strtab)
1628 return 0;
3af9a47b
NC
1629
1630 if (abfd->flags & BFD_IN_MEMORY)
1631 {
1632 struct bfd_in_memory *b;
1633
1634 b = (struct bfd_in_memory *) abfd->iostream;
1635
1636 if ((sym->stroff + sym->strsize) > b->size)
1637 {
1638 bfd_set_error (bfd_error_file_truncated);
1639 return -1;
1640 }
f075ee0c 1641 sym->strtab = (char *) b->buffer + sym->stroff;
3af9a47b 1642 }
046b007d 1643 else
3af9a47b 1644 {
046b007d
TG
1645 sym->strtab = bfd_alloc (abfd, sym->strsize);
1646 if (sym->strtab == NULL)
1647 return -1;
1648
1649 if (bfd_seek (abfd, sym->stroff, SEEK_SET) != 0
1650 || bfd_bread ((PTR) sym->strtab, sym->strsize, abfd) != sym->strsize)
1651 {
1652 bfd_set_error (bfd_error_file_truncated);
1653 return -1;
1654 }
3af9a47b
NC
1655 }
1656
1657 return 0;
1658}
1659
046b007d
TG
1660static int
1661bfd_mach_o_scan_read_symtab_symbols (bfd *abfd)
3af9a47b 1662{
046b007d
TG
1663 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
1664 bfd_mach_o_symtab_command *sym = mdata->symtab;
3af9a47b
NC
1665 unsigned long i;
1666 int ret;
1667
046b007d
TG
1668 if (sym->symbols)
1669 return 0;
1670
92bc0e80 1671 sym->symbols = bfd_alloc (abfd, sym->nsyms * sizeof (bfd_mach_o_asymbol));
3af9a47b
NC
1672
1673 if (sym->symbols == NULL)
1674 {
1675 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbols: unable to allocate memory for symbols\n");
a95a4550 1676 return -1;
3af9a47b 1677 }
a95a4550 1678
046b007d 1679 ret = bfd_mach_o_scan_read_symtab_strtab (abfd);
3af9a47b
NC
1680 if (ret != 0)
1681 return ret;
1682
1683 for (i = 0; i < sym->nsyms; i++)
1684 {
1685 ret = bfd_mach_o_scan_read_symtab_symbol (abfd, sym, &sym->symbols[i], i);
1686 if (ret != 0)
1687 return ret;
1688 }
a95a4550 1689
3af9a47b
NC
1690 return 0;
1691}
1692
1693int
116c20d2
NC
1694bfd_mach_o_scan_read_dysymtab_symbol (bfd *abfd,
1695 bfd_mach_o_dysymtab_command *dysym,
1696 bfd_mach_o_symtab_command *sym,
92bc0e80 1697 bfd_mach_o_asymbol *s,
116c20d2 1698 unsigned long i)
3af9a47b
NC
1699{
1700 unsigned long isymoff = dysym->indirectsymoff + (i * 4);
1701 unsigned long symindex;
1702 unsigned char buf[4];
1703
1704 BFD_ASSERT (i < dysym->nindirectsyms);
a95a4550 1705
c2f09c75
TG
1706 if (bfd_seek (abfd, isymoff, SEEK_SET) != 0
1707 || bfd_bread ((PTR) buf, 4, abfd) != 4)
3af9a47b
NC
1708 {
1709 fprintf (stderr, "bfd_mach_o_scan_read_dysymtab_symbol: unable to read %lu bytes at %lu\n",
1710 (unsigned long) 4, isymoff);
1711 return -1;
1712 }
1713 symindex = bfd_h_get_32 (abfd, buf);
a95a4550 1714
3af9a47b
NC
1715 return bfd_mach_o_scan_read_symtab_symbol (abfd, sym, s, symindex);
1716}
1717
1718static const char *
116c20d2 1719bfd_mach_o_i386_flavour_string (unsigned int flavour)
3af9a47b
NC
1720{
1721 switch ((int) flavour)
1722 {
15e1c58a
TG
1723 case BFD_MACH_O_x86_THREAD_STATE32: return "x86_THREAD_STATE32";
1724 case BFD_MACH_O_x86_FLOAT_STATE32: return "x86_FLOAT_STATE32";
1725 case BFD_MACH_O_x86_EXCEPTION_STATE32: return "x86_EXCEPTION_STATE32";
1726 case BFD_MACH_O_x86_THREAD_STATE64: return "x86_THREAD_STATE64";
1727 case BFD_MACH_O_x86_FLOAT_STATE64: return "x86_FLOAT_STATE64";
1728 case BFD_MACH_O_x86_EXCEPTION_STATE64: return "x86_EXCEPTION_STATE64";
1729 case BFD_MACH_O_x86_THREAD_STATE: return "x86_THREAD_STATE";
1730 case BFD_MACH_O_x86_FLOAT_STATE: return "x86_FLOAT_STATE";
1731 case BFD_MACH_O_x86_EXCEPTION_STATE: return "x86_EXCEPTION_STATE";
1732 case BFD_MACH_O_x86_DEBUG_STATE32: return "x86_DEBUG_STATE32";
1733 case BFD_MACH_O_x86_DEBUG_STATE64: return "x86_DEBUG_STATE64";
1734 case BFD_MACH_O_x86_DEBUG_STATE: return "x86_DEBUG_STATE";
b32e07d7 1735 case BFD_MACH_O_x86_THREAD_STATE_NONE: return "x86_THREAD_STATE_NONE";
3af9a47b
NC
1736 default: return "UNKNOWN";
1737 }
1738}
1739
1740static const char *
116c20d2 1741bfd_mach_o_ppc_flavour_string (unsigned int flavour)
3af9a47b
NC
1742{
1743 switch ((int) flavour)
1744 {
b32e07d7
TG
1745 case BFD_MACH_O_PPC_THREAD_STATE: return "PPC_THREAD_STATE";
1746 case BFD_MACH_O_PPC_FLOAT_STATE: return "PPC_FLOAT_STATE";
1747 case BFD_MACH_O_PPC_EXCEPTION_STATE: return "PPC_EXCEPTION_STATE";
1748 case BFD_MACH_O_PPC_VECTOR_STATE: return "PPC_VECTOR_STATE";
1749 case BFD_MACH_O_PPC_THREAD_STATE64: return "PPC_THREAD_STATE64";
1750 case BFD_MACH_O_PPC_EXCEPTION_STATE64: return "PPC_EXCEPTION_STATE64";
3af9a47b
NC
1751 default: return "UNKNOWN";
1752 }
1753}
1754
1755static int
116c20d2
NC
1756bfd_mach_o_scan_read_dylinker (bfd *abfd,
1757 bfd_mach_o_load_command *command)
3af9a47b
NC
1758{
1759 bfd_mach_o_dylinker_command *cmd = &command->command.dylinker;
1760 unsigned char buf[4];
1761 unsigned int nameoff;
3af9a47b
NC
1762
1763 BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLINKER)
1764 || (command->type == BFD_MACH_O_LC_LOAD_DYLINKER));
1765
c2f09c75
TG
1766 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
1767 || bfd_bread ((PTR) buf, 4, abfd) != 4)
3af9a47b
NC
1768 return -1;
1769
1770 nameoff = bfd_h_get_32 (abfd, buf + 0);
1771
1772 cmd->name_offset = command->offset + nameoff;
1773 cmd->name_len = command->len - nameoff;
b32e07d7
TG
1774 cmd->name_str = bfd_alloc (abfd, cmd->name_len);
1775 if (cmd->name_str == NULL)
3af9a47b 1776 return -1;
b32e07d7
TG
1777 if (bfd_seek (abfd, cmd->name_offset, SEEK_SET) != 0
1778 || bfd_bread (cmd->name_str, cmd->name_len, abfd) != cmd->name_len)
3af9a47b 1779 return -1;
3af9a47b
NC
1780 return 0;
1781}
1782
1783static int
116c20d2 1784bfd_mach_o_scan_read_dylib (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
1785{
1786 bfd_mach_o_dylib_command *cmd = &command->command.dylib;
1787 unsigned char buf[16];
1788 unsigned int nameoff;
3af9a47b 1789
046b007d
TG
1790 switch (command->type)
1791 {
1792 case BFD_MACH_O_LC_LOAD_DYLIB:
046b007d 1793 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
046b007d 1794 case BFD_MACH_O_LC_ID_DYLIB:
046b007d 1795 case BFD_MACH_O_LC_REEXPORT_DYLIB:
046b007d
TG
1796 break;
1797 default:
b32e07d7
TG
1798 BFD_FAIL ();
1799 return -1;
046b007d 1800 }
3af9a47b 1801
c2f09c75
TG
1802 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
1803 || bfd_bread ((PTR) buf, 16, abfd) != 16)
3af9a47b
NC
1804 return -1;
1805
1806 nameoff = bfd_h_get_32 (abfd, buf + 0);
1807 cmd->timestamp = bfd_h_get_32 (abfd, buf + 4);
1808 cmd->current_version = bfd_h_get_32 (abfd, buf + 8);
1809 cmd->compatibility_version = bfd_h_get_32 (abfd, buf + 12);
1810
1811 cmd->name_offset = command->offset + nameoff;
1812 cmd->name_len = command->len - nameoff;
b32e07d7
TG
1813 cmd->name_str = bfd_alloc (abfd, cmd->name_len);
1814 if (cmd->name_str == NULL)
3af9a47b 1815 return -1;
b32e07d7
TG
1816 if (bfd_seek (abfd, cmd->name_offset, SEEK_SET) != 0
1817 || bfd_bread (cmd->name_str, cmd->name_len, abfd) != cmd->name_len)
3af9a47b 1818 return -1;
3af9a47b
NC
1819 return 0;
1820}
1821
1822static int
116c20d2
NC
1823bfd_mach_o_scan_read_prebound_dylib (bfd *abfd ATTRIBUTE_UNUSED,
1824 bfd_mach_o_load_command *command ATTRIBUTE_UNUSED)
3af9a47b
NC
1825{
1826 /* bfd_mach_o_prebound_dylib_command *cmd = &command->command.prebound_dylib; */
1827
1828 BFD_ASSERT (command->type == BFD_MACH_O_LC_PREBOUND_DYLIB);
1829 return 0;
1830}
1831
1832static int
116c20d2 1833bfd_mach_o_scan_read_thread (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b 1834{
b32e07d7 1835 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b
NC
1836 bfd_mach_o_thread_command *cmd = &command->command.thread;
1837 unsigned char buf[8];
92bc0e80 1838 unsigned int offset;
3af9a47b
NC
1839 unsigned int nflavours;
1840 unsigned int i;
1841
1842 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
1843 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
1844
b32e07d7 1845 /* Count the number of threads. */
3af9a47b
NC
1846 offset = 8;
1847 nflavours = 0;
1848 while (offset != command->len)
1849 {
1850 if (offset >= command->len)
1851 return -1;
1852
c2f09c75
TG
1853 if (bfd_seek (abfd, command->offset + offset, SEEK_SET) != 0
1854 || bfd_bread ((PTR) buf, 8, abfd) != 8)
3af9a47b
NC
1855 return -1;
1856
1857 offset += 8 + bfd_h_get_32 (abfd, buf + 4) * 4;
1858 nflavours++;
1859 }
1860
b32e07d7
TG
1861 /* Allocate threads. */
1862 cmd->flavours = bfd_alloc
1863 (abfd, nflavours * sizeof (bfd_mach_o_thread_flavour));
3af9a47b
NC
1864 if (cmd->flavours == NULL)
1865 return -1;
1866 cmd->nflavours = nflavours;
1867
1868 offset = 8;
1869 nflavours = 0;
1870 while (offset != command->len)
1871 {
1872 if (offset >= command->len)
1873 return -1;
1874
1875 if (nflavours >= cmd->nflavours)
1876 return -1;
1877
c2f09c75
TG
1878 if (bfd_seek (abfd, command->offset + offset, SEEK_SET) != 0
1879 || bfd_bread ((PTR) buf, 8, abfd) != 8)
3af9a47b
NC
1880 return -1;
1881
1882 cmd->flavours[nflavours].flavour = bfd_h_get_32 (abfd, buf);
1883 cmd->flavours[nflavours].offset = command->offset + offset + 8;
1884 cmd->flavours[nflavours].size = bfd_h_get_32 (abfd, buf + 4) * 4;
1885 offset += cmd->flavours[nflavours].size + 8;
1886 nflavours++;
1887 }
1888
1889 for (i = 0; i < nflavours; i++)
1890 {
1891 asection *bfdsec;
1892 unsigned int snamelen;
1893 char *sname;
1894 const char *flavourstr;
1895 const char *prefix = "LC_THREAD";
a95a4550
AM
1896 unsigned int j = 0;
1897
3af9a47b
NC
1898 switch (mdata->header.cputype)
1899 {
1900 case BFD_MACH_O_CPU_TYPE_POWERPC:
1e8a024a 1901 case BFD_MACH_O_CPU_TYPE_POWERPC_64:
3af9a47b
NC
1902 flavourstr = bfd_mach_o_ppc_flavour_string (cmd->flavours[i].flavour);
1903 break;
1904 case BFD_MACH_O_CPU_TYPE_I386:
1e8a024a 1905 case BFD_MACH_O_CPU_TYPE_X86_64:
3af9a47b
NC
1906 flavourstr = bfd_mach_o_i386_flavour_string (cmd->flavours[i].flavour);
1907 break;
1908 default:
1909 flavourstr = "UNKNOWN_ARCHITECTURE";
1910 break;
1911 }
a95a4550 1912
3af9a47b 1913 snamelen = strlen (prefix) + 1 + 20 + 1 + strlen (flavourstr) + 1;
116c20d2 1914 sname = bfd_alloc (abfd, snamelen);
3af9a47b
NC
1915 if (sname == NULL)
1916 return -1;
1917
1918 for (;;)
1919 {
a95a4550
AM
1920 sprintf (sname, "%s.%s.%u", prefix, flavourstr, j);
1921 if (bfd_get_section_by_name (abfd, sname) == NULL)
3af9a47b 1922 break;
a95a4550 1923 j++;
3af9a47b
NC
1924 }
1925
117ed4f8 1926 bfdsec = bfd_make_section_with_flags (abfd, sname, SEC_HAS_CONTENTS);
a95a4550 1927
3af9a47b
NC
1928 bfdsec->vma = 0;
1929 bfdsec->lma = 0;
eea6121a 1930 bfdsec->size = cmd->flavours[i].size;
3af9a47b
NC
1931 bfdsec->filepos = cmd->flavours[i].offset;
1932 bfdsec->alignment_power = 0x0;
3af9a47b
NC
1933
1934 cmd->section = bfdsec;
1935 }
1936
1937 return 0;
1938}
1939
a95a4550 1940static int
116c20d2 1941bfd_mach_o_scan_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b 1942{
046b007d 1943 bfd_mach_o_dysymtab_command *cmd = &command->command.dysymtab;
b32e07d7 1944 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b
NC
1945 unsigned char buf[72];
1946
1947 BFD_ASSERT (command->type == BFD_MACH_O_LC_DYSYMTAB);
1948
c2f09c75
TG
1949 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
1950 || bfd_bread ((PTR) buf, 72, abfd) != 72)
3af9a47b
NC
1951 return -1;
1952
046b007d
TG
1953 cmd->ilocalsym = bfd_h_get_32 (abfd, buf + 0);
1954 cmd->nlocalsym = bfd_h_get_32 (abfd, buf + 4);
1955 cmd->iextdefsym = bfd_h_get_32 (abfd, buf + 8);
1956 cmd->nextdefsym = bfd_h_get_32 (abfd, buf + 12);
1957 cmd->iundefsym = bfd_h_get_32 (abfd, buf + 16);
1958 cmd->nundefsym = bfd_h_get_32 (abfd, buf + 20);
1959 cmd->tocoff = bfd_h_get_32 (abfd, buf + 24);
1960 cmd->ntoc = bfd_h_get_32 (abfd, buf + 28);
1961 cmd->modtaboff = bfd_h_get_32 (abfd, buf + 32);
1962 cmd->nmodtab = bfd_h_get_32 (abfd, buf + 36);
1963 cmd->extrefsymoff = bfd_h_get_32 (abfd, buf + 40);
1964 cmd->nextrefsyms = bfd_h_get_32 (abfd, buf + 44);
1965 cmd->indirectsymoff = bfd_h_get_32 (abfd, buf + 48);
1966 cmd->nindirectsyms = bfd_h_get_32 (abfd, buf + 52);
1967 cmd->extreloff = bfd_h_get_32 (abfd, buf + 56);
1968 cmd->nextrel = bfd_h_get_32 (abfd, buf + 60);
1969 cmd->locreloff = bfd_h_get_32 (abfd, buf + 64);
1970 cmd->nlocrel = bfd_h_get_32 (abfd, buf + 68);
1971
1972 if (cmd->nmodtab != 0)
1973 {
1974 char buf[56];
1975 unsigned int i;
1976 int wide = bfd_mach_o_wide_p (abfd);
1977 unsigned int module_len = wide ? 56 : 52;
1978
1979 cmd->dylib_module =
1980 bfd_alloc (abfd, cmd->nmodtab * sizeof (bfd_mach_o_dylib_module));
1981 if (cmd->dylib_module == NULL)
1982 return -1;
1983
1984 if (bfd_seek (abfd, cmd->modtaboff, SEEK_SET) != 0)
1985 return -1;
1986
1987 for (i = 0; i < cmd->nmodtab; i++)
1988 {
1989 bfd_mach_o_dylib_module *module = &cmd->dylib_module[i];
1990 unsigned long v;
1991
1992 if (bfd_bread ((PTR) buf, module_len, abfd) != module_len)
1993 return -1;
1994
1995 module->module_name_idx = bfd_h_get_32 (abfd, buf + 0);
1996 module->iextdefsym = bfd_h_get_32 (abfd, buf + 4);
1997 module->nextdefsym = bfd_h_get_32 (abfd, buf + 8);
1998 module->irefsym = bfd_h_get_32 (abfd, buf + 12);
1999 module->nrefsym = bfd_h_get_32 (abfd, buf + 16);
2000 module->ilocalsym = bfd_h_get_32 (abfd, buf + 20);
2001 module->nlocalsym = bfd_h_get_32 (abfd, buf + 24);
2002 module->iextrel = bfd_h_get_32 (abfd, buf + 28);
2003 module->nextrel = bfd_h_get_32 (abfd, buf + 32);
2004 v = bfd_h_get_32 (abfd, buf +36);
2005 module->iinit = v & 0xffff;
2006 module->iterm = (v >> 16) & 0xffff;
2007 v = bfd_h_get_32 (abfd, buf + 40);
2008 module->ninit = v & 0xffff;
2009 module->nterm = (v >> 16) & 0xffff;
2010 if (wide)
2011 {
2012 module->objc_module_info_size = bfd_h_get_32 (abfd, buf + 44);
2013 module->objc_module_info_addr = bfd_h_get_64 (abfd, buf + 48);
2014 }
2015 else
2016 {
2017 module->objc_module_info_addr = bfd_h_get_32 (abfd, buf + 44);
2018 module->objc_module_info_size = bfd_h_get_32 (abfd, buf + 48);
2019 }
2020 }
2021 }
2022
2023 if (cmd->ntoc != 0)
2024 {
2025 char buf[8];
2026 unsigned int i;
2027
2028 cmd->dylib_toc = bfd_alloc
2029 (abfd, cmd->ntoc * sizeof (bfd_mach_o_dylib_table_of_content));
2030 if (cmd->dylib_toc == NULL)
2031 return -1;
2032
2033 if (bfd_seek (abfd, cmd->tocoff, SEEK_SET) != 0)
2034 return -1;
2035
2036 for (i = 0; i < cmd->ntoc; i++)
2037 {
2038 bfd_mach_o_dylib_table_of_content *toc = &cmd->dylib_toc[i];
2039
2040 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
2041 return -1;
2042
2043 toc->symbol_index = bfd_h_get_32 (abfd, buf + 0);
2044 toc->module_index = bfd_h_get_32 (abfd, buf + 4);
2045 }
2046 }
2047
2048 if (cmd->nindirectsyms != 0)
2049 {
2050 char buf[4];
2051 unsigned int i;
2052
2053 cmd->indirect_syms = bfd_alloc
2054 (abfd, cmd->nindirectsyms * sizeof (unsigned int));
2055 if (cmd->indirect_syms == NULL)
2056 return -1;
2057
2058 if (bfd_seek (abfd, cmd->indirectsymoff, SEEK_SET) != 0)
2059 return -1;
2060
2061 for (i = 0; i < cmd->nindirectsyms; i++)
2062 {
2063 unsigned int *is = &cmd->indirect_syms[i];
2064
2065 if (bfd_bread ((PTR) buf, 4, abfd) != 4)
2066 return -1;
2067
2068 *is = bfd_h_get_32 (abfd, buf + 0);
2069 }
2070 }
2071
2072 if (cmd->nextrefsyms != 0)
2073 {
2074 char buf[4];
2075 unsigned long v;
2076 unsigned int i;
2077
2078 cmd->ext_refs = bfd_alloc
2079 (abfd, cmd->nextrefsyms * sizeof (bfd_mach_o_dylib_reference));
2080 if (cmd->ext_refs == NULL)
2081 return -1;
2082
2083 if (bfd_seek (abfd, cmd->extrefsymoff, SEEK_SET) != 0)
2084 return -1;
2085
2086 for (i = 0; i < cmd->nextrefsyms; i++)
2087 {
2088 bfd_mach_o_dylib_reference *ref = &cmd->ext_refs[i];
2089
2090 if (bfd_bread ((PTR) buf, 4, abfd) != 4)
2091 return -1;
2092
b32e07d7
TG
2093 /* Fields isym and flags are written as bit-fields, thus we need
2094 a specific processing for endianness. */
046b007d 2095 v = bfd_h_get_32 (abfd, buf + 0);
b32e07d7
TG
2096 if (bfd_big_endian (abfd))
2097 {
2098 ref->isym = (v >> 8) & 0xffffff;
2099 ref->flags = v & 0xff;
2100 }
2101 else
2102 {
2103 ref->isym = v & 0xffffff;
2104 ref->flags = (v >> 24) & 0xff;
2105 }
046b007d
TG
2106 }
2107 }
3af9a47b 2108
b32e07d7
TG
2109 if (mdata->dysymtab)
2110 return -1;
2111 mdata->dysymtab = cmd;
2112
3af9a47b
NC
2113 return 0;
2114}
2115
a95a4550 2116static int
116c20d2 2117bfd_mach_o_scan_read_symtab (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b 2118{
046b007d
TG
2119 bfd_mach_o_symtab_command *symtab = &command->command.symtab;
2120 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b 2121 unsigned char buf[16];
3af9a47b
NC
2122
2123 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
2124
c2f09c75
TG
2125 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
2126 || bfd_bread ((PTR) buf, 16, abfd) != 16)
3af9a47b 2127 return -1;
a95a4550 2128
046b007d
TG
2129 symtab->symoff = bfd_h_get_32 (abfd, buf);
2130 symtab->nsyms = bfd_h_get_32 (abfd, buf + 4);
2131 symtab->stroff = bfd_h_get_32 (abfd, buf + 8);
2132 symtab->strsize = bfd_h_get_32 (abfd, buf + 12);
2133 symtab->symbols = NULL;
2134 symtab->strtab = NULL;
3af9a47b 2135
046b007d 2136 if (symtab->nsyms != 0)
15e1c58a
TG
2137 abfd->flags |= HAS_SYMS;
2138
046b007d
TG
2139 if (mdata->symtab)
2140 return -1;
2141 mdata->symtab = symtab;
3af9a47b
NC
2142 return 0;
2143}
2144
15e1c58a
TG
2145static int
2146bfd_mach_o_scan_read_uuid (bfd *abfd, bfd_mach_o_load_command *command)
2147{
2148 bfd_mach_o_uuid_command *cmd = &command->command.uuid;
2149 asection *bfdsec;
2150 char *sname;
2151 static const char prefix[] = "LC_UUID";
2152
2153 BFD_ASSERT (command->type == BFD_MACH_O_LC_UUID);
2154
c2f09c75
TG
2155 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
2156 || bfd_bread ((PTR) cmd->uuid, 16, abfd) != 16)
15e1c58a
TG
2157 return -1;
2158
2159 sname = bfd_alloc (abfd, strlen (prefix) + 1);
2160 if (sname == NULL)
2161 return -1;
2162 strcpy (sname, prefix);
2163
2164 bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS);
2165 if (bfdsec == NULL)
2166 return -1;
2167
2168 bfdsec->vma = 0;
2169 bfdsec->lma = 0;
2170 bfdsec->size = command->len - 8;
2171 bfdsec->filepos = command->offset + 8;
2172 bfdsec->alignment_power = 0;
2173
2174 cmd->section = bfdsec;
2175
2176 return 0;
2177}
2178
046b007d
TG
2179static int
2180bfd_mach_o_scan_read_linkedit (bfd *abfd, bfd_mach_o_load_command *command)
2181{
2182 bfd_mach_o_linkedit_command *cmd = &command->command.linkedit;
2183 char buf[8];
2184
2185 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
2186 || bfd_bread ((PTR) buf, 8, abfd) != 8)
2187 return -1;
2188
2189 cmd->dataoff = bfd_get_32 (abfd, buf + 0);
2190 cmd->datasize = bfd_get_32 (abfd, buf + 4);
2191 return 0;
2192}
2193
2194static int
2195bfd_mach_o_scan_read_str (bfd *abfd, bfd_mach_o_load_command *command)
2196{
2197 bfd_mach_o_str_command *cmd = &command->command.str;
2198 char buf[8];
2199 unsigned long off;
2200
2201 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
2202 || bfd_bread ((PTR) buf, 4, abfd) != 4)
2203 return -1;
2204
2205 off = bfd_get_32 (abfd, buf + 0);
2206 cmd->stroff = command->offset + off;
2207 cmd->str_len = command->len - off;
2208 cmd->str = bfd_alloc (abfd, cmd->str_len);
2209 if (cmd->str == NULL)
2210 return -1;
2211 if (bfd_seek (abfd, cmd->stroff, SEEK_SET) != 0
2212 || bfd_bread ((PTR) cmd->str, cmd->str_len, abfd) != cmd->str_len)
2213 return -1;
2214 return 0;
2215}
2216
3af9a47b 2217static int
1e8a024a
TG
2218bfd_mach_o_scan_read_segment (bfd *abfd,
2219 bfd_mach_o_load_command *command,
2220 unsigned int wide)
3af9a47b 2221{
1e8a024a 2222 unsigned char buf[64];
3af9a47b
NC
2223 bfd_mach_o_segment_command *seg = &command->command.segment;
2224 unsigned long i;
a95a4550 2225
1e8a024a
TG
2226 if (wide)
2227 {
2228 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT_64);
3af9a47b 2229
c2f09c75
TG
2230 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
2231 || bfd_bread ((PTR) buf, 64, abfd) != 64)
1e8a024a 2232 return -1;
3af9a47b 2233
1e8a024a 2234 memcpy (seg->segname, buf, 16);
15e1c58a 2235 seg->segname[16] = '\0';
1e8a024a
TG
2236
2237 seg->vmaddr = bfd_h_get_64 (abfd, buf + 16);
2238 seg->vmsize = bfd_h_get_64 (abfd, buf + 24);
2239 seg->fileoff = bfd_h_get_64 (abfd, buf + 32);
2240 seg->filesize = bfd_h_get_64 (abfd, buf + 40);
2241 seg->maxprot = bfd_h_get_32 (abfd, buf + 48);
2242 seg->initprot = bfd_h_get_32 (abfd, buf + 52);
2243 seg->nsects = bfd_h_get_32 (abfd, buf + 56);
2244 seg->flags = bfd_h_get_32 (abfd, buf + 60);
2245 }
2246 else
2247 {
2248 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
2249
c2f09c75
TG
2250 if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0
2251 || bfd_bread ((PTR) buf, 48, abfd) != 48)
1e8a024a
TG
2252 return -1;
2253
2254 memcpy (seg->segname, buf, 16);
15e1c58a 2255 seg->segname[16] = '\0';
1e8a024a
TG
2256
2257 seg->vmaddr = bfd_h_get_32 (abfd, buf + 16);
2258 seg->vmsize = bfd_h_get_32 (abfd, buf + 20);
2259 seg->fileoff = bfd_h_get_32 (abfd, buf + 24);
2260 seg->filesize = bfd_h_get_32 (abfd, buf + 28);
2261 seg->maxprot = bfd_h_get_32 (abfd, buf + 32);
2262 seg->initprot = bfd_h_get_32 (abfd, buf + 36);
2263 seg->nsects = bfd_h_get_32 (abfd, buf + 40);
2264 seg->flags = bfd_h_get_32 (abfd, buf + 44);
2265 }
3af9a47b 2266
3af9a47b
NC
2267 if (seg->nsects != 0)
2268 {
154a1ee5
TG
2269 seg->sections = bfd_alloc (abfd, seg->nsects
2270 * sizeof (bfd_mach_o_section));
3af9a47b
NC
2271 if (seg->sections == NULL)
2272 return -1;
a95a4550 2273
3af9a47b
NC
2274 for (i = 0; i < seg->nsects; i++)
2275 {
1e8a024a 2276 bfd_vma segoff;
154a1ee5 2277 if (wide)
c2f09c75 2278 segoff = command->offset + BFD_MACH_O_LC_SEGMENT_64_SIZE
154a1ee5
TG
2279 + (i * BFD_MACH_O_SECTION_64_SIZE);
2280 else
c2f09c75 2281 segoff = command->offset + BFD_MACH_O_LC_SEGMENT_SIZE
154a1ee5 2282 + (i * BFD_MACH_O_SECTION_SIZE);
3af9a47b 2283
1e8a024a 2284 if (bfd_mach_o_scan_read_section
15e1c58a 2285 (abfd, &seg->sections[i], segoff, seg->initprot, wide) != 0)
3af9a47b 2286 return -1;
a95a4550 2287 }
3af9a47b
NC
2288 }
2289
2290 return 0;
2291}
2292
1e8a024a
TG
2293static int
2294bfd_mach_o_scan_read_segment_32 (bfd *abfd, bfd_mach_o_load_command *command)
2295{
2296 return bfd_mach_o_scan_read_segment (abfd, command, 0);
2297}
2298
2299static int
2300bfd_mach_o_scan_read_segment_64 (bfd *abfd, bfd_mach_o_load_command *command)
2301{
2302 return bfd_mach_o_scan_read_segment (abfd, command, 1);
2303}
2304
3af9a47b 2305static int
116c20d2 2306bfd_mach_o_scan_read_command (bfd *abfd, bfd_mach_o_load_command *command)
3af9a47b
NC
2307{
2308 unsigned char buf[8];
2309
046b007d 2310 /* Read command type and length. */
c2f09c75
TG
2311 if (bfd_seek (abfd, command->offset, SEEK_SET) != 0
2312 || bfd_bread ((PTR) buf, 8, abfd) != 8)
3af9a47b
NC
2313 return -1;
2314
154a1ee5 2315 command->type = bfd_h_get_32 (abfd, buf) & ~BFD_MACH_O_LC_REQ_DYLD;
e84d6fca 2316 command->type_required = (bfd_h_get_32 (abfd, buf) & BFD_MACH_O_LC_REQ_DYLD
154a1ee5 2317 ? TRUE : FALSE);
3af9a47b
NC
2318 command->len = bfd_h_get_32 (abfd, buf + 4);
2319
2320 switch (command->type)
2321 {
2322 case BFD_MACH_O_LC_SEGMENT:
1e8a024a
TG
2323 if (bfd_mach_o_scan_read_segment_32 (abfd, command) != 0)
2324 return -1;
2325 break;
2326 case BFD_MACH_O_LC_SEGMENT_64:
2327 if (bfd_mach_o_scan_read_segment_64 (abfd, command) != 0)
3af9a47b
NC
2328 return -1;
2329 break;
2330 case BFD_MACH_O_LC_SYMTAB:
2331 if (bfd_mach_o_scan_read_symtab (abfd, command) != 0)
2332 return -1;
2333 break;
2334 case BFD_MACH_O_LC_SYMSEG:
2335 break;
2336 case BFD_MACH_O_LC_THREAD:
2337 case BFD_MACH_O_LC_UNIXTHREAD:
2338 if (bfd_mach_o_scan_read_thread (abfd, command) != 0)
2339 return -1;
2340 break;
2341 case BFD_MACH_O_LC_LOAD_DYLINKER:
2342 case BFD_MACH_O_LC_ID_DYLINKER:
2343 if (bfd_mach_o_scan_read_dylinker (abfd, command) != 0)
2344 return -1;
2345 break;
2346 case BFD_MACH_O_LC_LOAD_DYLIB:
2347 case BFD_MACH_O_LC_ID_DYLIB:
2348 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
046b007d 2349 case BFD_MACH_O_LC_REEXPORT_DYLIB:
3af9a47b
NC
2350 if (bfd_mach_o_scan_read_dylib (abfd, command) != 0)
2351 return -1;
2352 break;
2353 case BFD_MACH_O_LC_PREBOUND_DYLIB:
2354 if (bfd_mach_o_scan_read_prebound_dylib (abfd, command) != 0)
2355 return -1;
2356 break;
2357 case BFD_MACH_O_LC_LOADFVMLIB:
2358 case BFD_MACH_O_LC_IDFVMLIB:
2359 case BFD_MACH_O_LC_IDENT:
2360 case BFD_MACH_O_LC_FVMFILE:
2361 case BFD_MACH_O_LC_PREPAGE:
2362 case BFD_MACH_O_LC_ROUTINES:
046b007d 2363 break;
3af9a47b 2364 case BFD_MACH_O_LC_SUB_FRAMEWORK:
046b007d
TG
2365 case BFD_MACH_O_LC_SUB_UMBRELLA:
2366 case BFD_MACH_O_LC_SUB_LIBRARY:
2367 case BFD_MACH_O_LC_SUB_CLIENT:
2368 if (bfd_mach_o_scan_read_str (abfd, command) != 0)
2369 return -1;
3af9a47b
NC
2370 break;
2371 case BFD_MACH_O_LC_DYSYMTAB:
2372 if (bfd_mach_o_scan_read_dysymtab (abfd, command) != 0)
2373 return -1;
2374 break;
3af9a47b
NC
2375 case BFD_MACH_O_LC_TWOLEVEL_HINTS:
2376 case BFD_MACH_O_LC_PREBIND_CKSUM:
2377 break;
15e1c58a
TG
2378 case BFD_MACH_O_LC_UUID:
2379 if (bfd_mach_o_scan_read_uuid (abfd, command) != 0)
2380 return -1;
2381 break;
2382 case BFD_MACH_O_LC_CODE_SIGNATURE:
846b9259 2383 case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO:
046b007d
TG
2384 if (bfd_mach_o_scan_read_linkedit (abfd, command) != 0)
2385 return -1;
15e1c58a 2386 break;
3af9a47b
NC
2387 default:
2388 fprintf (stderr, "unable to read unknown load command 0x%lx\n",
2389 (unsigned long) command->type);
2390 break;
2391 }
2392
2393 return 0;
2394}
2395
2396static void
116c20d2 2397bfd_mach_o_flatten_sections (bfd *abfd)
3af9a47b 2398{
046b007d 2399 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b
NC
2400 long csect = 0;
2401 unsigned long i, j;
a95a4550 2402
15e1c58a 2403 /* Count total number of sections. */
3af9a47b
NC
2404 mdata->nsects = 0;
2405
2406 for (i = 0; i < mdata->header.ncmds; i++)
2407 {
1e8a024a
TG
2408 if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT
2409 || mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT_64)
3af9a47b 2410 {
e84d6fca
AM
2411 bfd_mach_o_segment_command *seg;
2412
2413 seg = &mdata->commands[i].command.segment;
3af9a47b
NC
2414 mdata->nsects += seg->nsects;
2415 }
2416 }
2417
15e1c58a 2418 /* Allocate sections array. */
e84d6fca
AM
2419 mdata->sections = bfd_alloc (abfd,
2420 mdata->nsects * sizeof (bfd_mach_o_section *));
15e1c58a
TG
2421
2422 /* Fill the array. */
3af9a47b
NC
2423 csect = 0;
2424
2425 for (i = 0; i < mdata->header.ncmds; i++)
2426 {
1e8a024a
TG
2427 if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT
2428 || mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT_64)
3af9a47b 2429 {
e84d6fca 2430 bfd_mach_o_segment_command *seg;
3af9a47b 2431
e84d6fca 2432 seg = &mdata->commands[i].command.segment;
3af9a47b
NC
2433 BFD_ASSERT (csect + seg->nsects <= mdata->nsects);
2434
2435 for (j = 0; j < seg->nsects; j++)
2436 mdata->sections[csect++] = &seg->sections[j];
2437 }
2438 }
2439}
2440
2441int
116c20d2 2442bfd_mach_o_scan_start_address (bfd *abfd)
3af9a47b 2443{
046b007d 2444 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b
NC
2445 bfd_mach_o_thread_command *cmd = NULL;
2446 unsigned long i;
2447
2448 for (i = 0; i < mdata->header.ncmds; i++)
2449 {
2450 if ((mdata->commands[i].type == BFD_MACH_O_LC_THREAD) ||
2451 (mdata->commands[i].type == BFD_MACH_O_LC_UNIXTHREAD))
2452 {
2453 if (cmd == NULL)
2454 cmd = &mdata->commands[i].command.thread;
2455 else
2456 return 0;
2457 }
2458 }
2459
2460 if (cmd == NULL)
2461 return 0;
2462
2463 for (i = 0; i < cmd->nflavours; i++)
2464 {
a95a4550 2465 if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_I386)
e84d6fca 2466 && (cmd->flavours[i].flavour
15e1c58a 2467 == (unsigned long) BFD_MACH_O_x86_THREAD_STATE32))
3af9a47b
NC
2468 {
2469 unsigned char buf[4];
2470
c2f09c75
TG
2471 if (bfd_seek (abfd, cmd->flavours[i].offset + 40, SEEK_SET) != 0
2472 || bfd_bread (buf, 4, abfd) != 4)
3af9a47b
NC
2473 return -1;
2474
2475 abfd->start_address = bfd_h_get_32 (abfd, buf);
2476 }
a95a4550 2477 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC)
3af9a47b
NC
2478 && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE))
2479 {
2480 unsigned char buf[4];
2481
c2f09c75
TG
2482 if (bfd_seek (abfd, cmd->flavours[i].offset + 0, SEEK_SET) != 0
2483 || bfd_bread (buf, 4, abfd) != 4)
3af9a47b
NC
2484 return -1;
2485
2486 abfd->start_address = bfd_h_get_32 (abfd, buf);
2487 }
1e8a024a 2488 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC_64)
b32e07d7 2489 && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE64))
1e8a024a
TG
2490 {
2491 unsigned char buf[8];
2492
c2f09c75
TG
2493 if (bfd_seek (abfd, cmd->flavours[i].offset + 0, SEEK_SET) != 0
2494 || bfd_bread (buf, 8, abfd) != 8)
1e8a024a
TG
2495 return -1;
2496
2497 abfd->start_address = bfd_h_get_64 (abfd, buf);
2498 }
2499 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_X86_64)
2500 && (cmd->flavours[i].flavour == BFD_MACH_O_x86_THREAD_STATE64))
2501 {
2502 unsigned char buf[8];
2503
c2f09c75
TG
2504 if (bfd_seek (abfd, cmd->flavours[i].offset + (16 * 8), SEEK_SET) != 0
2505 || bfd_bread (buf, 8, abfd) != 8)
1e8a024a
TG
2506 return -1;
2507
2508 abfd->start_address = bfd_h_get_64 (abfd, buf);
2509 }
3af9a47b
NC
2510 }
2511
2512 return 0;
2513}
2514
2515int
116c20d2
NC
2516bfd_mach_o_scan (bfd *abfd,
2517 bfd_mach_o_header *header,
2518 bfd_mach_o_data_struct *mdata)
3af9a47b
NC
2519{
2520 unsigned int i;
3af9a47b
NC
2521 enum bfd_architecture cputype;
2522 unsigned long cpusubtype;
1e8a024a
TG
2523 unsigned int hdrsize;
2524
c2f09c75 2525 hdrsize = mach_o_wide_p (header) ?
154a1ee5 2526 BFD_MACH_O_HEADER_64_SIZE : BFD_MACH_O_HEADER_SIZE;
3af9a47b 2527
3af9a47b 2528 mdata->header = *header;
3af9a47b 2529
154a1ee5 2530 abfd->flags = abfd->flags & BFD_IN_MEMORY;
15e1c58a
TG
2531 switch (header->filetype)
2532 {
2533 case BFD_MACH_O_MH_OBJECT:
2534 abfd->flags |= HAS_RELOC;
2535 break;
2536 case BFD_MACH_O_MH_EXECUTE:
2537 abfd->flags |= EXEC_P;
2538 break;
2539 case BFD_MACH_O_MH_DYLIB:
2540 case BFD_MACH_O_MH_BUNDLE:
2541 abfd->flags |= DYNAMIC;
2542 break;
2543 }
2544
3af9a47b
NC
2545 abfd->tdata.mach_o_data = mdata;
2546
e84d6fca
AM
2547 bfd_mach_o_convert_architecture (header->cputype, header->cpusubtype,
2548 &cputype, &cpusubtype);
3af9a47b
NC
2549 if (cputype == bfd_arch_unknown)
2550 {
2551 fprintf (stderr, "bfd_mach_o_scan: unknown architecture 0x%lx/0x%lx\n",
2552 header->cputype, header->cpusubtype);
2553 return -1;
2554 }
2555
2556 bfd_set_arch_mach (abfd, cputype, cpusubtype);
a95a4550 2557
3af9a47b
NC
2558 if (header->ncmds != 0)
2559 {
046b007d
TG
2560 mdata->commands = bfd_alloc
2561 (abfd, header->ncmds * sizeof (bfd_mach_o_load_command));
3af9a47b
NC
2562 if (mdata->commands == NULL)
2563 return -1;
a95a4550 2564
3af9a47b
NC
2565 for (i = 0; i < header->ncmds; i++)
2566 {
2567 bfd_mach_o_load_command *cur = &mdata->commands[i];
2568
2569 if (i == 0)
1e8a024a 2570 cur->offset = hdrsize;
3af9a47b
NC
2571 else
2572 {
2573 bfd_mach_o_load_command *prev = &mdata->commands[i - 1];
2574 cur->offset = prev->offset + prev->len;
2575 }
2576
2577 if (bfd_mach_o_scan_read_command (abfd, cur) < 0)
2578 return -1;
a95a4550 2579 }
3af9a47b
NC
2580 }
2581
2582 if (bfd_mach_o_scan_start_address (abfd) < 0)
7e3102a7 2583 return -1;
3af9a47b
NC
2584
2585 bfd_mach_o_flatten_sections (abfd);
3af9a47b
NC
2586 return 0;
2587}
2588
b34976b6 2589bfd_boolean
154a1ee5 2590bfd_mach_o_mkobject_init (bfd *abfd)
3af9a47b
NC
2591{
2592 bfd_mach_o_data_struct *mdata = NULL;
2593
116c20d2 2594 mdata = bfd_alloc (abfd, sizeof (bfd_mach_o_data_struct));
3af9a47b 2595 if (mdata == NULL)
b34976b6 2596 return FALSE;
3af9a47b
NC
2597 abfd->tdata.mach_o_data = mdata;
2598
2599 mdata->header.magic = 0;
2600 mdata->header.cputype = 0;
2601 mdata->header.cpusubtype = 0;
2602 mdata->header.filetype = 0;
2603 mdata->header.ncmds = 0;
2604 mdata->header.sizeofcmds = 0;
2605 mdata->header.flags = 0;
2606 mdata->header.byteorder = BFD_ENDIAN_UNKNOWN;
2607 mdata->commands = NULL;
3af9a47b
NC
2608 mdata->nsects = 0;
2609 mdata->sections = NULL;
3af9a47b 2610
b34976b6 2611 return TRUE;
3af9a47b
NC
2612}
2613
2614const bfd_target *
154a1ee5
TG
2615bfd_mach_o_header_p (bfd *abfd,
2616 bfd_mach_o_filetype filetype,
2617 bfd_mach_o_cpu_type cputype)
3af9a47b 2618{
e84d6fca 2619 struct bfd_preserve preserve;
3af9a47b
NC
2620 bfd_mach_o_header header;
2621
e84d6fca 2622 preserve.marker = NULL;
154a1ee5 2623 if (!bfd_mach_o_read_header (abfd, &header))
e84d6fca 2624 goto wrong;
3af9a47b 2625
e84d6fca
AM
2626 if (! (header.byteorder == BFD_ENDIAN_BIG
2627 || header.byteorder == BFD_ENDIAN_LITTLE))
3af9a47b 2628 {
e84d6fca 2629 fprintf (stderr, "unknown header byte-order value 0x%lx\n",
0af1713e 2630 (unsigned long) header.byteorder);
e84d6fca 2631 goto wrong;
3af9a47b
NC
2632 }
2633
e84d6fca
AM
2634 if (! ((header.byteorder == BFD_ENDIAN_BIG
2635 && abfd->xvec->byteorder == BFD_ENDIAN_BIG
2636 && abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
2637 || (header.byteorder == BFD_ENDIAN_LITTLE
2638 && abfd->xvec->byteorder == BFD_ENDIAN_LITTLE
2639 && abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)))
2640 goto wrong;
3af9a47b 2641
154a1ee5
TG
2642 /* Check cputype and filetype.
2643 In case of wildcard, do not accept magics that are handled by existing
2644 targets. */
2645 if (cputype)
2646 {
2647 if (header.cputype != cputype)
2648 goto wrong;
2649 }
2650 else
2651 {
2652 switch (header.cputype)
2653 {
2654 case BFD_MACH_O_CPU_TYPE_I386:
2655 /* Handled by mach-o-i386 */
2656 goto wrong;
2657 default:
2658 break;
2659 }
2660 }
2661 if (filetype)
2662 {
2663 if (header.filetype != filetype)
2664 goto wrong;
2665 }
2666 else
2667 {
2668 switch (header.filetype)
2669 {
2670 case BFD_MACH_O_MH_CORE:
2671 /* Handled by core_p */
2672 goto wrong;
2673 default:
2674 break;
2675 }
2676 }
2677
e84d6fca
AM
2678 preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct));
2679 if (preserve.marker == NULL
2680 || !bfd_preserve_save (abfd, &preserve))
2681 goto fail;
3af9a47b 2682
e84d6fca
AM
2683 if (bfd_mach_o_scan (abfd, &header,
2684 (bfd_mach_o_data_struct *) preserve.marker) != 0)
2685 goto wrong;
a95a4550 2686
e84d6fca 2687 bfd_preserve_finish (abfd, &preserve);
3af9a47b 2688 return abfd->xvec;
e84d6fca
AM
2689
2690 wrong:
2691 bfd_set_error (bfd_error_wrong_format);
2692
2693 fail:
2694 if (preserve.marker != NULL)
2695 bfd_preserve_restore (abfd, &preserve);
2696 return NULL;
3af9a47b
NC
2697}
2698
154a1ee5
TG
2699static const bfd_target *
2700bfd_mach_o_gen_object_p (bfd *abfd)
3af9a47b 2701{
154a1ee5
TG
2702 return bfd_mach_o_header_p (abfd, 0, 0);
2703}
e84d6fca 2704
154a1ee5
TG
2705static const bfd_target *
2706bfd_mach_o_gen_core_p (bfd *abfd)
2707{
2708 return bfd_mach_o_header_p (abfd, BFD_MACH_O_MH_CORE, 0);
3af9a47b
NC
2709}
2710
2711typedef struct mach_o_fat_archentry
2712{
2713 unsigned long cputype;
2714 unsigned long cpusubtype;
2715 unsigned long offset;
2716 unsigned long size;
2717 unsigned long align;
3af9a47b
NC
2718} mach_o_fat_archentry;
2719
2720typedef struct mach_o_fat_data_struct
2721{
2722 unsigned long magic;
2723 unsigned long nfat_arch;
2724 mach_o_fat_archentry *archentries;
2725} mach_o_fat_data_struct;
2726
2727const bfd_target *
116c20d2 2728bfd_mach_o_archive_p (bfd *abfd)
3af9a47b 2729{
e84d6fca 2730 mach_o_fat_data_struct *adata = NULL;
3af9a47b
NC
2731 unsigned char buf[20];
2732 unsigned long i;
2733
c2f09c75
TG
2734 if (bfd_seek (abfd, 0, SEEK_SET) != 0
2735 || bfd_bread ((PTR) buf, 8, abfd) != 8)
e84d6fca 2736 goto error;
3af9a47b 2737
116c20d2 2738 adata = bfd_alloc (abfd, sizeof (mach_o_fat_data_struct));
3af9a47b 2739 if (adata == NULL)
e84d6fca 2740 goto error;
a95a4550 2741
3af9a47b
NC
2742 adata->magic = bfd_getb32 (buf);
2743 adata->nfat_arch = bfd_getb32 (buf + 4);
2744 if (adata->magic != 0xcafebabe)
e84d6fca 2745 goto error;
27cc28f9
AS
2746 /* Avoid matching Java bytecode files, which have the same magic number.
2747 In the Java bytecode file format this field contains the JVM version,
2748 which starts at 43.0. */
2749 if (adata->nfat_arch > 30)
2750 goto error;
3af9a47b 2751
c2f09c75 2752 adata->archentries =
3af9a47b
NC
2753 bfd_alloc (abfd, adata->nfat_arch * sizeof (mach_o_fat_archentry));
2754 if (adata->archentries == NULL)
e84d6fca 2755 goto error;
3af9a47b
NC
2756
2757 for (i = 0; i < adata->nfat_arch; i++)
2758 {
c2f09c75
TG
2759 if (bfd_seek (abfd, 8 + 20 * i, SEEK_SET) != 0
2760 || bfd_bread ((PTR) buf, 20, abfd) != 20)
e84d6fca 2761 goto error;
3af9a47b
NC
2762 adata->archentries[i].cputype = bfd_getb32 (buf);
2763 adata->archentries[i].cpusubtype = bfd_getb32 (buf + 4);
2764 adata->archentries[i].offset = bfd_getb32 (buf + 8);
2765 adata->archentries[i].size = bfd_getb32 (buf + 12);
2766 adata->archentries[i].align = bfd_getb32 (buf + 16);
3af9a47b
NC
2767 }
2768
2769 abfd->tdata.mach_o_fat_data = adata;
2770 return abfd->xvec;
e84d6fca
AM
2771
2772 error:
2773 if (adata != NULL)
2774 bfd_release (abfd, adata);
2775 bfd_set_error (bfd_error_wrong_format);
2776 return NULL;
3af9a47b
NC
2777}
2778
2779bfd *
116c20d2 2780bfd_mach_o_openr_next_archived_file (bfd *archive, bfd *prev)
3af9a47b 2781{
e84d6fca 2782 mach_o_fat_data_struct *adata;
3af9a47b
NC
2783 mach_o_fat_archentry *entry = NULL;
2784 unsigned long i;
15e1c58a 2785 bfd *nbfd;
15e1c58a
TG
2786 enum bfd_architecture arch_type;
2787 unsigned long arch_subtype;
3af9a47b 2788
e84d6fca 2789 adata = (mach_o_fat_data_struct *) archive->tdata.mach_o_fat_data;
3af9a47b
NC
2790 BFD_ASSERT (adata != NULL);
2791
2792 /* Find index of previous entry. */
2793 if (prev == NULL)
2794 i = 0; /* Start at first one. */
2795 else
2796 {
2797 for (i = 0; i < adata->nfat_arch; i++)
2798 {
15e1c58a 2799 if (adata->archentries[i].offset == prev->origin)
3af9a47b
NC
2800 break;
2801 }
2802
2803 if (i == adata->nfat_arch)
2804 {
2805 /* Not found. */
2806 bfd_set_error (bfd_error_bad_value);
a95a4550 2807 return NULL;
3af9a47b
NC
2808 }
2809 i++; /* Get next entry. */
2810 }
a95a4550 2811
3af9a47b
NC
2812 if (i >= adata->nfat_arch)
2813 {
2814 bfd_set_error (bfd_error_no_more_archived_files);
2815 return NULL;
2816 }
2817
2818 entry = &adata->archentries[i];
15e1c58a
TG
2819 nbfd = _bfd_new_bfd_contained_in (archive);
2820 if (nbfd == NULL)
2821 return NULL;
2822
2823 nbfd->origin = entry->offset;
2824
2825 bfd_mach_o_convert_architecture (entry->cputype, entry->cpusubtype,
2826 &arch_type, &arch_subtype);
846b9259
TG
2827 /* Create the member filename.
2828 Use FILENAME:ARCH_NAME. */
2829 {
2830 char *s = NULL;
2831 const char *arch_name;
2832 size_t arch_file_len = strlen (bfd_get_filename (archive));
2833
2834 arch_name = bfd_printable_arch_mach (arch_type, arch_subtype);
2835 s = bfd_malloc (arch_file_len + 1 + strlen (arch_name) + 1);
2836 if (s == NULL)
2837 return NULL;
2838 memcpy (s, bfd_get_filename (archive), arch_file_len);
2839 s[arch_file_len] = ':';
2840 strcpy (s + arch_file_len + 1, arch_name);
2841 nbfd->filename = s;
2842 }
15e1c58a 2843 nbfd->iostream = NULL;
846b9259 2844 bfd_set_arch_mach (nbfd, arch_type, arch_subtype);
3af9a47b 2845
15e1c58a 2846 return nbfd;
3af9a47b
NC
2847}
2848
846b9259
TG
2849/* If ABFD format is FORMAT and architecture is ARCH, return it.
2850 If ABFD is a fat image containing a member that corresponds to FORMAT
2851 and ARCH, returns it.
2852 In other case, returns NULL.
2853 This function allows transparent uses of fat images. */
2854bfd *
2855bfd_mach_o_fat_extract (bfd *abfd,
2856 bfd_format format,
2857 const bfd_arch_info_type *arch)
2858{
2859 bfd *res;
2860 mach_o_fat_data_struct *adata;
2861 unsigned int i;
2862
2863 if (bfd_check_format (abfd, format))
2864 {
2865 if (bfd_get_arch_info (abfd) == arch)
2866 return abfd;
2867 return NULL;
2868 }
2869 if (!bfd_check_format (abfd, bfd_archive)
2870 || abfd->xvec != &mach_o_fat_vec)
2871 return NULL;
c2f09c75 2872
846b9259
TG
2873 /* This is a Mach-O fat image. */
2874 adata = (mach_o_fat_data_struct *) abfd->tdata.mach_o_fat_data;
2875 BFD_ASSERT (adata != NULL);
2876
2877 for (i = 0; i < adata->nfat_arch; i++)
2878 {
2879 struct mach_o_fat_archentry *e = &adata->archentries[i];
2880 enum bfd_architecture cpu_type;
2881 unsigned long cpu_subtype;
2882
2883 bfd_mach_o_convert_architecture (e->cputype, e->cpusubtype,
2884 &cpu_type, &cpu_subtype);
2885 if (cpu_type != arch->arch || cpu_subtype != arch->mach)
2886 continue;
2887
2888 /* The architecture is found. */
2889 res = _bfd_new_bfd_contained_in (abfd);
2890 if (res == NULL)
2891 return NULL;
2892
2893 res->origin = e->offset;
2894
2895 res->filename = strdup (abfd->filename);
2896 res->iostream = NULL;
2897
2898 if (bfd_check_format (res, format))
2899 {
2900 BFD_ASSERT (bfd_get_arch_info (res) == arch);
2901 return res;
2902 }
2903 bfd_close (res);
2904 return NULL;
2905 }
2906
2907 return NULL;
2908}
2909
e84d6fca 2910int
116c20d2
NC
2911bfd_mach_o_lookup_section (bfd *abfd,
2912 asection *section,
2913 bfd_mach_o_load_command **mcommand,
2914 bfd_mach_o_section **msection)
3af9a47b 2915{
046b007d 2916 struct mach_o_data_struct *md = bfd_mach_o_get_data (abfd);
3af9a47b
NC
2917 unsigned int i, j, num;
2918
2919 bfd_mach_o_load_command *ncmd = NULL;
2920 bfd_mach_o_section *nsect = NULL;
2921
2922 BFD_ASSERT (mcommand != NULL);
2923 BFD_ASSERT (msection != NULL);
2924
2925 num = 0;
2926 for (i = 0; i < md->header.ncmds; i++)
2927 {
2928 struct bfd_mach_o_load_command *cmd = &md->commands[i];
2929 struct bfd_mach_o_segment_command *seg = NULL;
2930
1e8a024a
TG
2931 if (cmd->type != BFD_MACH_O_LC_SEGMENT
2932 || cmd->type != BFD_MACH_O_LC_SEGMENT_64)
3af9a47b
NC
2933 continue;
2934 seg = &cmd->command.segment;
a95a4550 2935
3af9a47b
NC
2936 for (j = 0; j < seg->nsects; j++)
2937 {
2938 struct bfd_mach_o_section *sect = &seg->sections[j];
2939
2940 if (sect->bfdsection == section)
2941 {
2942 if (num == 0)
b32e07d7
TG
2943 {
2944 nsect = sect;
2945 ncmd = cmd;
2946 }
3af9a47b
NC
2947 num++;
2948 }
2949 }
2950 }
a95a4550 2951
3af9a47b
NC
2952 *mcommand = ncmd;
2953 *msection = nsect;
2954 return num;
2955}
2956
2957int
116c20d2
NC
2958bfd_mach_o_lookup_command (bfd *abfd,
2959 bfd_mach_o_load_command_type type,
2960 bfd_mach_o_load_command **mcommand)
3af9a47b 2961{
046b007d 2962 struct mach_o_data_struct *md = bfd_mach_o_get_data (abfd);
3af9a47b
NC
2963 bfd_mach_o_load_command *ncmd = NULL;
2964 unsigned int i, num;
2965
3af9a47b
NC
2966 BFD_ASSERT (md != NULL);
2967 BFD_ASSERT (mcommand != NULL);
2968
2969 num = 0;
2970 for (i = 0; i < md->header.ncmds; i++)
2971 {
2972 struct bfd_mach_o_load_command *cmd = &md->commands[i];
2973
2974 if (cmd->type != type)
2975 continue;
2976
2977 if (num == 0)
2978 ncmd = cmd;
2979 num++;
2980 }
2981
2982 *mcommand = ncmd;
2983 return num;
2984}
2985
2986unsigned long
116c20d2 2987bfd_mach_o_stack_addr (enum bfd_mach_o_cpu_type type)
3af9a47b
NC
2988{
2989 switch (type)
2990 {
2991 case BFD_MACH_O_CPU_TYPE_MC680x0:
2992 return 0x04000000;
2993 case BFD_MACH_O_CPU_TYPE_MC88000:
2994 return 0xffffe000;
2995 case BFD_MACH_O_CPU_TYPE_POWERPC:
2996 return 0xc0000000;
2997 case BFD_MACH_O_CPU_TYPE_I386:
2998 return 0xc0000000;
2999 case BFD_MACH_O_CPU_TYPE_SPARC:
3000 return 0xf0000000;
3001 case BFD_MACH_O_CPU_TYPE_I860:
3002 return 0;
3003 case BFD_MACH_O_CPU_TYPE_HPPA:
e84d6fca 3004 return 0xc0000000 - 0x04000000;
3af9a47b
NC
3005 default:
3006 return 0;
3007 }
3008}
3009
046b007d 3010typedef struct bfd_mach_o_xlat_name
15e1c58a 3011{
046b007d
TG
3012 const char *name;
3013 unsigned long val;
3014}
3015bfd_mach_o_xlat_name;
3016
3017static void
3018bfd_mach_o_print_flags (const bfd_mach_o_xlat_name *table,
3019 unsigned long val,
3020 FILE *file)
3021{
3022 int first = 1;
3023
3024 for (; table->name; table++)
3025 {
3026 if (table->val & val)
3027 {
3028 if (!first)
3029 fprintf (file, "+");
3030 fprintf (file, "%s", table->name);
3031 val &= ~table->val;
3032 first = 0;
3033 }
3034 }
3035 if (val)
3036 {
3037 if (!first)
3038 fprintf (file, "+");
3039 fprintf (file, "0x%lx", val);
3040 return;
3041 }
3042 if (first)
3043 fprintf (file, "-");
3044}
3045
3046static const char *
3047bfd_mach_o_get_name (const bfd_mach_o_xlat_name *table, unsigned long val)
3048{
3049 for (; table->name; table++)
3050 if (table->val == val)
3051 return table->name;
3052 return "*UNKNOWN*";
3053}
3054
3055static bfd_mach_o_xlat_name bfd_mach_o_cpu_name[] =
3056{
3057 { "vax", BFD_MACH_O_CPU_TYPE_VAX},
3058 { "mc680x0", BFD_MACH_O_CPU_TYPE_MC680x0},
3059 { "i386", BFD_MACH_O_CPU_TYPE_I386},
3060 { "mips", BFD_MACH_O_CPU_TYPE_MIPS},
3061 { "mc98000", BFD_MACH_O_CPU_TYPE_MC98000},
3062 { "hppa", BFD_MACH_O_CPU_TYPE_HPPA},
3063 { "arm", BFD_MACH_O_CPU_TYPE_ARM},
3064 { "mc88000", BFD_MACH_O_CPU_TYPE_MC88000},
3065 { "sparc", BFD_MACH_O_CPU_TYPE_SPARC},
3066 { "i860", BFD_MACH_O_CPU_TYPE_I860},
3067 { "alpha", BFD_MACH_O_CPU_TYPE_ALPHA},
3068 { "powerpc", BFD_MACH_O_CPU_TYPE_POWERPC},
3069 { "powerpc_64", BFD_MACH_O_CPU_TYPE_POWERPC_64},
3070 { "x86_64", BFD_MACH_O_CPU_TYPE_X86_64},
3071 { NULL, 0}
3072};
3073
3074static bfd_mach_o_xlat_name bfd_mach_o_filetype_name[] =
3075{
3076 { "object", BFD_MACH_O_MH_OBJECT},
3077 { "execute", BFD_MACH_O_MH_EXECUTE},
3078 { "fvmlib", BFD_MACH_O_MH_FVMLIB},
3079 { "core", BFD_MACH_O_MH_CORE},
3080 { "preload", BFD_MACH_O_MH_PRELOAD},
3081 { "dylib", BFD_MACH_O_MH_DYLIB},
3082 { "dylinker", BFD_MACH_O_MH_DYLINKER},
3083 { "bundle", BFD_MACH_O_MH_BUNDLE},
3084 { NULL, 0}
3085};
3086
3087static bfd_mach_o_xlat_name bfd_mach_o_header_flags_name[] =
3088{
3089 { "noundefs", BFD_MACH_O_MH_NOUNDEFS },
3090 { "incrlink", BFD_MACH_O_MH_INCRLINK },
3091 { "dyldlink", BFD_MACH_O_MH_DYLDLINK },
3092 { "bindatload", BFD_MACH_O_MH_BINDATLOAD },
3093 { "prebound", BFD_MACH_O_MH_PREBOUND },
3094 { "split_segs", BFD_MACH_O_MH_SPLIT_SEGS },
3095 { "lazy_init", BFD_MACH_O_MH_LAZY_INIT },
3096 { "twolevel", BFD_MACH_O_MH_TWOLEVEL },
3097 { "force_flat", BFD_MACH_O_MH_FORCE_FLAT },
3098 { "nomultidefs", BFD_MACH_O_MH_NOMULTIDEFS },
3099 { "nofixprebinding", BFD_MACH_O_MH_NOFIXPREBINDING },
3100 { "prebindable", BFD_MACH_O_MH_PREBINDABLE },
3101 { "allmodsbound", BFD_MACH_O_MH_ALLMODSBOUND },
3102 { "subsections_via_symbols", BFD_MACH_O_MH_SUBSECTIONS_VIA_SYMBOLS },
3103 { "canonical", BFD_MACH_O_MH_CANONICAL },
3104 { "weak_defines", BFD_MACH_O_MH_WEAK_DEFINES },
3105 { "binds_to_weak", BFD_MACH_O_MH_BINDS_TO_WEAK },
3106 { "allow_stack_execution", BFD_MACH_O_MH_ALLOW_STACK_EXECUTION },
3107 { "root_safe", BFD_MACH_O_MH_ROOT_SAFE },
3108 { "setuid_safe", BFD_MACH_O_MH_SETUID_SAFE },
3109 { "no_reexported_dylibs", BFD_MACH_O_MH_NO_REEXPORTED_DYLIBS },
3110 { "pie", BFD_MACH_O_MH_PIE },
3111 { NULL, 0}
3112};
3113
3114static bfd_mach_o_xlat_name bfd_mach_o_section_type_name[] =
3115{
3116 { "regular", BFD_MACH_O_S_REGULAR},
3117 { "zerofill", BFD_MACH_O_S_ZEROFILL},
3118 { "cstring_literals", BFD_MACH_O_S_CSTRING_LITERALS},
3119 { "4byte_literals", BFD_MACH_O_S_4BYTE_LITERALS},
3120 { "8byte_literals", BFD_MACH_O_S_8BYTE_LITERALS},
3121 { "literal_pointers", BFD_MACH_O_S_LITERAL_POINTERS},
3122 { "non_lazy_symbol_pointers", BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS},
3123 { "lazy_symbol_pointers", BFD_MACH_O_S_LAZY_SYMBOL_POINTERS},
3124 { "symbol_stubs", BFD_MACH_O_S_SYMBOL_STUBS},
3125 { "mod_init_func_pointers", BFD_MACH_O_S_MOD_INIT_FUNC_POINTERS},
3126 { "mod_fini_func_pointers", BFD_MACH_O_S_MOD_FINI_FUNC_POINTERS},
3127 { "coalesced", BFD_MACH_O_S_COALESCED},
3128 { "gb_zerofill", BFD_MACH_O_S_GB_ZEROFILL},
3129 { "interposing", BFD_MACH_O_S_INTERPOSING},
3130 { "16byte_literals", BFD_MACH_O_S_16BYTE_LITERALS},
3131 { "dtrace_dof", BFD_MACH_O_S_DTRACE_DOF},
3132 { "lazy_dylib_symbol_pointers", BFD_MACH_O_S_LAZY_DYLIB_SYMBOL_POINTERS},
3133 { NULL, 0}
3134};
3135
3136static bfd_mach_o_xlat_name bfd_mach_o_section_attribute_name[] =
3137{
3138 { "loc_reloc", BFD_MACH_O_S_ATTR_LOC_RELOC },
3139 { "ext_reloc", BFD_MACH_O_S_ATTR_EXT_RELOC },
3140 { "some_instructions", BFD_MACH_O_S_ATTR_SOME_INSTRUCTIONS },
3141 { "debug", BFD_MACH_O_S_ATTR_DEBUG },
3142 { "modifying_code", BFD_MACH_O_S_SELF_MODIFYING_CODE },
3143 { "live_support", BFD_MACH_O_S_ATTR_LIVE_SUPPORT },
3144 { "no_dead_strip", BFD_MACH_O_S_ATTR_NO_DEAD_STRIP },
3145 { "strip_static_syms", BFD_MACH_O_S_ATTR_STRIP_STATIC_SYMS },
3146 { "no_toc", BFD_MACH_O_S_ATTR_NO_TOC },
3147 { "pure_instructions", BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS },
3148 { NULL, 0}
3149};
3150
3151static bfd_mach_o_xlat_name bfd_mach_o_load_command_name[] =
3152{
3153 { "segment", BFD_MACH_O_LC_SEGMENT},
3154 { "symtab", BFD_MACH_O_LC_SYMTAB},
3155 { "symseg", BFD_MACH_O_LC_SYMSEG},
3156 { "thread", BFD_MACH_O_LC_THREAD},
3157 { "unixthread", BFD_MACH_O_LC_UNIXTHREAD},
3158 { "loadfvmlib", BFD_MACH_O_LC_LOADFVMLIB},
3159 { "idfvmlib", BFD_MACH_O_LC_IDFVMLIB},
3160 { "ident", BFD_MACH_O_LC_IDENT},
3161 { "fvmfile", BFD_MACH_O_LC_FVMFILE},
3162 { "prepage", BFD_MACH_O_LC_PREPAGE},
3163 { "dysymtab", BFD_MACH_O_LC_DYSYMTAB},
3164 { "load_dylib", BFD_MACH_O_LC_LOAD_DYLIB},
3165 { "id_dylib", BFD_MACH_O_LC_ID_DYLIB},
3166 { "load_dylinker", BFD_MACH_O_LC_LOAD_DYLINKER},
3167 { "id_dylinker", BFD_MACH_O_LC_ID_DYLINKER},
3168 { "prebound_dylib", BFD_MACH_O_LC_PREBOUND_DYLIB},
3169 { "routines", BFD_MACH_O_LC_ROUTINES},
3170 { "sub_framework", BFD_MACH_O_LC_SUB_FRAMEWORK},
3171 { "sub_umbrella", BFD_MACH_O_LC_SUB_UMBRELLA},
3172 { "sub_client", BFD_MACH_O_LC_SUB_CLIENT},
3173 { "sub_library", BFD_MACH_O_LC_SUB_LIBRARY},
3174 { "twolevel_hints", BFD_MACH_O_LC_TWOLEVEL_HINTS},
3175 { "prebind_cksum", BFD_MACH_O_LC_PREBIND_CKSUM},
3176 { "load_weak_dylib", BFD_MACH_O_LC_LOAD_WEAK_DYLIB},
3177 { "segment_64", BFD_MACH_O_LC_SEGMENT_64},
3178 { "routines_64", BFD_MACH_O_LC_ROUTINES_64},
3179 { "uuid", BFD_MACH_O_LC_UUID},
3180 { "rpath", BFD_MACH_O_LC_RPATH},
3181 { "code_signature", BFD_MACH_O_LC_CODE_SIGNATURE},
3182 { "segment_split_info", BFD_MACH_O_LC_SEGMENT_SPLIT_INFO},
3183 { "reexport_dylib", BFD_MACH_O_LC_REEXPORT_DYLIB},
3184 { "lazy_load_dylib", BFD_MACH_O_LC_LAZY_LOAD_DYLIB},
3185 { "encryption_info", BFD_MACH_O_LC_ENCRYPTION_INFO},
3186 { NULL, 0}
3187};
3188
3189static void
3190bfd_mach_o_print_private_header (bfd *abfd, FILE *file)
3191{
3192 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3193 bfd_mach_o_header *h = &mdata->header;
3194
3195 fprintf (file, _("Mach-O header:\n"));
3196 fprintf (file, _(" magic : %08lx\n"), h->magic);
3197 fprintf (file, _(" cputype : %08lx (%s)\n"), h->cputype,
3198 bfd_mach_o_get_name (bfd_mach_o_cpu_name, h->cputype));
3199 fprintf (file, _(" cpusubtype: %08lx\n"), h->cpusubtype);
3200 fprintf (file, _(" filetype : %08lx (%s)\n"),
3201 h->filetype,
3202 bfd_mach_o_get_name (bfd_mach_o_filetype_name, h->filetype));
3203 fprintf (file, _(" ncmds : %08lx\n"), h->ncmds);
3204 fprintf (file, _(" sizeofcmds: %08lx\n"), h->sizeofcmds);
3205 fprintf (file, _(" flags : %08lx ("), h->flags);
3206 bfd_mach_o_print_flags (bfd_mach_o_header_flags_name, h->flags, file);
3207 fprintf (file, _(")\n"));
b8674692 3208 fprintf (file, _(" reserved : %08x\n"), h->reserved);
046b007d
TG
3209}
3210
3211static void
3212bfd_mach_o_print_section_map (bfd *abfd, FILE *file)
3213{
3214 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
15e1c58a
TG
3215 unsigned int i, j;
3216 unsigned int sec_nbr = 0;
3217
3218 fprintf (file, _("Segments and Sections:\n"));
3219 fprintf (file, _(" #: Segment name Section name Address\n"));
3220
3221 for (i = 0; i < mdata->header.ncmds; i++)
3222 {
3223 bfd_mach_o_segment_command *seg;
3224
3225 if (mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT
3226 && mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT_64)
3227 continue;
3228
3229 seg = &mdata->commands[i].command.segment;
3230
3231 fprintf (file, "[Segment %-16s ", seg->segname);
3232 fprintf_vma (file, seg->vmaddr);
3233 fprintf (file, "-");
3234 fprintf_vma (file, seg->vmaddr + seg->vmsize - 1);
3235 fputc (' ', file);
3236 fputc (seg->initprot & BFD_MACH_O_PROT_READ ? 'r' : '-', file);
3237 fputc (seg->initprot & BFD_MACH_O_PROT_WRITE ? 'w' : '-', file);
3238 fputc (seg->initprot & BFD_MACH_O_PROT_EXECUTE ? 'x' : '-', file);
3239 fprintf (file, "]\n");
3240 for (j = 0; j < seg->nsects; j++)
3241 {
3242 bfd_mach_o_section *sec = &seg->sections[j];
3243 fprintf (file, "%02u: %-16s %-16s ", ++sec_nbr,
3244 sec->segname, sec->sectname);
3245 fprintf_vma (file, sec->addr);
3246 fprintf (file, " ");
3247 fprintf_vma (file, sec->size);
3248 fprintf (file, " %08lx\n", sec->flags);
3249 }
3250 }
046b007d
TG
3251}
3252
3253/* Return the number of indirect symbols for a section.
3254 Must be called only for symbol pointer section and symbol stubs
3255 sections. */
3256
3257static unsigned int
3258bfd_mach_o_section_get_nbr_indirect (bfd *abfd, bfd_mach_o_section *sec)
3259{
3260 unsigned int elsz;
3261
3262 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
3263 {
3264 case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
3265 case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
3266 elsz = bfd_mach_o_wide_p (abfd) ? 8 : 4;
3267 return sec->size / elsz;
3268 case BFD_MACH_O_S_SYMBOL_STUBS:
3269 elsz = sec->reserved2;
3270 if (elsz)
3271 return sec->size / elsz;
3272 else
3273 return 0;
3274 default:
3275 BFD_FAIL ();
3276 return 0;
3277 }
3278}
3279
3280static void
3281bfd_mach_o_print_section (bfd *abfd ATTRIBUTE_UNUSED,
3282 bfd_mach_o_section *sec, FILE *file)
3283{
b32e07d7
TG
3284 fprintf (file, " Section: %-16s %-16s (bfdname: %s)\n",
3285 sec->sectname, sec->segname, sec->bfdsection->name);
046b007d
TG
3286 fprintf (file, " addr: ");
3287 fprintf_vma (file, sec->addr);
3288 fprintf (file, " size: ");
3289 fprintf_vma (file, sec->size);
3290 fprintf (file, " offset: ");
3291 fprintf_vma (file, sec->offset);
3292 fprintf (file, "\n");
3293 fprintf (file, " align: %ld", sec->align);
3294 fprintf (file, " nreloc: %lu reloff: ", sec->nreloc);
3295 fprintf_vma (file, sec->reloff);
3296 fprintf (file, "\n");
3297 fprintf (file, " flags: %08lx (type: %s", sec->flags,
3298 bfd_mach_o_get_name (bfd_mach_o_section_type_name,
3299 sec->flags & BFD_MACH_O_SECTION_TYPE_MASK));
3300 fprintf (file, " attr: ");
3301 bfd_mach_o_print_flags (bfd_mach_o_section_attribute_name,
3302 sec->flags & BFD_MACH_O_SECTION_ATTRIBUTES_MASK,
3303 file);
3304 fprintf (file, ")\n");
3305 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
3306 {
3307 case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
3308 case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
3309 case BFD_MACH_O_S_SYMBOL_STUBS:
3310 fprintf (file, " first indirect sym: %lu", sec->reserved1);
3311 fprintf (file, " (%u entries)",
3312 bfd_mach_o_section_get_nbr_indirect (abfd, sec));
3313 break;
3314 default:
3315 fprintf (file, " reserved1: 0x%lx", sec->reserved1);
3316 break;
3317 }
3318 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
3319 {
3320 case BFD_MACH_O_S_SYMBOL_STUBS:
3321 fprintf (file, " stub size: %lu", sec->reserved2);
3322 break;
3323 default:
3324 fprintf (file, " reserved2: 0x%lx", sec->reserved2);
3325 break;
3326 }
3327 fprintf (file, " reserved3: 0x%lx\n", sec->reserved3);
3328}
3329
3330static void
3331bfd_mach_o_print_segment (bfd *abfd ATTRIBUTE_UNUSED,
3332 bfd_mach_o_load_command *cmd, FILE *file)
3333{
3334 bfd_mach_o_segment_command *seg = &cmd->command.segment;
3335 unsigned int i;
3336
b32e07d7 3337 fprintf (file, " name: %s\n", *seg->segname ? seg->segname : "*none*");
046b007d
TG
3338 fprintf (file, " vmaddr: ");
3339 fprintf_vma (file, seg->vmaddr);
3340 fprintf (file, " vmsize: ");
3341 fprintf_vma (file, seg->vmsize);
3342 fprintf (file, "\n");
3343 fprintf (file, " fileoff: ");
3344 fprintf_vma (file, seg->fileoff);
3345 fprintf (file, " filesize: ");
3346 fprintf_vma (file, (bfd_vma)seg->filesize);
3347 fprintf (file, " endoff: ");
3348 fprintf_vma (file, (bfd_vma)(seg->fileoff + seg->filesize));
3349 fprintf (file, "\n");
3350 fprintf (file, " nsects: %lu ", seg->nsects);
3351 fprintf (file, " flags: %lx\n", seg->flags);
3352 for (i = 0; i < seg->nsects; i++)
3353 bfd_mach_o_print_section (abfd, &seg->sections[i], file);
3354}
3355
3356static void
3357bfd_mach_o_print_dysymtab (bfd *abfd ATTRIBUTE_UNUSED,
3358 bfd_mach_o_load_command *cmd, FILE *file)
3359{
3360 bfd_mach_o_dysymtab_command *dysymtab = &cmd->command.dysymtab;
3361 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3362 unsigned int i;
3363
b32e07d7 3364 fprintf (file, " local symbols: idx: %10lu num: %-8lu",
046b007d 3365 dysymtab->ilocalsym, dysymtab->nlocalsym);
b32e07d7
TG
3366 fprintf (file, " (nxtidx: %lu)\n",
3367 dysymtab->ilocalsym + dysymtab->nlocalsym);
3368 fprintf (file, " external symbols: idx: %10lu num: %-8lu",
046b007d 3369 dysymtab->iextdefsym, dysymtab->nextdefsym);
b32e07d7
TG
3370 fprintf (file, " (nxtidx: %lu)\n",
3371 dysymtab->iextdefsym + dysymtab->nextdefsym);
3372 fprintf (file, " undefined symbols: idx: %10lu num: %-8lu",
046b007d 3373 dysymtab->iundefsym, dysymtab->nundefsym);
b32e07d7
TG
3374 fprintf (file, " (nxtidx: %lu)\n",
3375 dysymtab->iundefsym + dysymtab->nundefsym);
046b007d
TG
3376 fprintf (file, " table of content: off: 0x%08lx num: %-8lu",
3377 dysymtab->tocoff, dysymtab->ntoc);
3378 fprintf (file, " (endoff: 0x%08lx)\n",
3379 dysymtab->tocoff
3380 + dysymtab->ntoc * BFD_MACH_O_TABLE_OF_CONTENT_SIZE);
3381 fprintf (file, " module table: off: 0x%08lx num: %-8lu",
3382 dysymtab->modtaboff, dysymtab->nmodtab);
3383 fprintf (file, " (endoff: 0x%08lx)\n",
3384 dysymtab->modtaboff + dysymtab->nmodtab
3385 * (mach_o_wide_p (&mdata->header) ?
3386 BFD_MACH_O_DYLIB_MODULE_64_SIZE : BFD_MACH_O_DYLIB_MODULE_SIZE));
3387 fprintf (file, " external reference table: off: 0x%08lx num: %-8lu",
3388 dysymtab->extrefsymoff, dysymtab->nextrefsyms);
3389 fprintf (file, " (endoff: 0x%08lx)\n",
3390 dysymtab->extrefsymoff
3391 + dysymtab->nextrefsyms * BFD_MACH_O_REFERENCE_SIZE);
3392 fprintf (file, " indirect symbol table: off: 0x%08lx num: %-8lu",
3393 dysymtab->indirectsymoff, dysymtab->nindirectsyms);
3394 fprintf (file, " (endoff: 0x%08lx)\n",
3395 dysymtab->indirectsymoff
3396 + dysymtab->nindirectsyms * BFD_MACH_O_INDIRECT_SYMBOL_SIZE);
3397 fprintf (file, " external relocation table: off: 0x%08lx num: %-8lu",
3398 dysymtab->extreloff, dysymtab->nextrel);
3399 fprintf (file, " (endoff: 0x%08lx)\n",
3400 dysymtab->extreloff + dysymtab->nextrel * BFD_MACH_O_RELENT_SIZE);
3401 fprintf (file, " local relocation table: off: 0x%08lx num: %-8lu",
3402 dysymtab->locreloff, dysymtab->nlocrel);
3403 fprintf (file, " (endoff: 0x%08lx)\n",
3404 dysymtab->locreloff + dysymtab->nlocrel * BFD_MACH_O_RELENT_SIZE);
3405
3406 if (dysymtab->ntoc > 0
3407 || dysymtab->nindirectsyms > 0
3408 || dysymtab->nextrefsyms > 0)
3409 {
3410 /* Try to read the symbols to display the toc or indirect symbols. */
3411 bfd_mach_o_scan_read_symtab_symbols (abfd);
3412 }
3413 else if (dysymtab->nmodtab > 0)
3414 {
3415 /* Try to read the strtab to display modules name. */
3416 bfd_mach_o_scan_read_symtab_strtab (abfd);
3417 }
3418
3419 for (i = 0; i < dysymtab->nmodtab; i++)
3420 {
3421 bfd_mach_o_dylib_module *module = &dysymtab->dylib_module[i];
3422 fprintf (file, " module %u:\n", i);
3423 fprintf (file, " name: %lu", module->module_name_idx);
3424 if (mdata->symtab && mdata->symtab->strtab)
3425 fprintf (file, ": %s",
3426 mdata->symtab->strtab + module->module_name_idx);
3427 fprintf (file, "\n");
3428 fprintf (file, " extdefsym: idx: %8lu num: %lu\n",
3429 module->iextdefsym, module->nextdefsym);
3430 fprintf (file, " refsym: idx: %8lu num: %lu\n",
3431 module->irefsym, module->nrefsym);
3432 fprintf (file, " localsym: idx: %8lu num: %lu\n",
3433 module->ilocalsym, module->nlocalsym);
3434 fprintf (file, " extrel: idx: %8lu num: %lu\n",
3435 module->iextrel, module->nextrel);
3436 fprintf (file, " init: idx: %8u num: %u\n",
3437 module->iinit, module->ninit);
3438 fprintf (file, " term: idx: %8u num: %u\n",
3439 module->iterm, module->nterm);
3440 fprintf (file, " objc_module_info: addr: ");
3441 fprintf_vma (file, module->objc_module_info_addr);
3442 fprintf (file, " size: %lu\n", module->objc_module_info_size);
3443 }
3444
3445 if (dysymtab->ntoc > 0)
3446 {
3447 bfd_mach_o_symtab_command *symtab = mdata->symtab;
3448
3449 fprintf (file, " table of content: (symbol/module)\n");
3450 for (i = 0; i < dysymtab->ntoc; i++)
3451 {
3452 bfd_mach_o_dylib_table_of_content *toc = &dysymtab->dylib_toc[i];
3453
3454 fprintf (file, " %4u: ", i);
3455 if (symtab && symtab->symbols && toc->symbol_index < symtab->nsyms)
3456 {
3457 const char *name = symtab->symbols[toc->symbol_index].symbol.name;
3458 fprintf (file, "%s (%lu)", name ? name : "*invalid*",
3459 toc->symbol_index);
3460 }
3461 else
3462 fprintf (file, "%lu", toc->symbol_index);
3463
3464 fprintf (file, " / ");
3465 if (symtab && symtab->strtab
3466 && toc->module_index < dysymtab->nmodtab)
3467 {
3468 bfd_mach_o_dylib_module *mod;
3469 mod = &dysymtab->dylib_module[toc->module_index];
3470 fprintf (file, "%s (%lu)",
3471 symtab->strtab + mod->module_name_idx,
3472 toc->module_index);
3473 }
3474 else
3475 fprintf (file, "%lu", toc->module_index);
3476
3477 fprintf (file, "\n");
3478 }
3479 }
3480
3481 if (dysymtab->nindirectsyms != 0)
3482 {
3483 fprintf (file, " indirect symbols:\n");
3484
3485 for (i = 0; i < mdata->nsects; i++)
3486 {
3487 bfd_mach_o_section *sec = mdata->sections[i];
3488 unsigned int j, first, last;
3489 bfd_mach_o_symtab_command *symtab = mdata->symtab;
3490
3491 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
3492 {
3493 case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
3494 case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
3495 case BFD_MACH_O_S_SYMBOL_STUBS:
3496 first = sec->reserved1;
3497 last = first + bfd_mach_o_section_get_nbr_indirect (abfd, sec);
3498 fprintf (file, " for section %s.%s:\n",
3499 sec->segname, sec->sectname);
3500 for (j = first; j < last; j++)
3501 {
3502 unsigned int isym = dysymtab->indirect_syms[j];
3503
3504 fprintf (file, " %5u: 0x%08x (%u)", j, isym, isym);
3505 if (isym & BFD_MACH_O_INDIRECT_SYMBOL_LOCAL)
3506 fprintf (file, " LOCAL");
3507 if (isym & BFD_MACH_O_INDIRECT_SYMBOL_ABS)
3508 fprintf (file, " ABSOLUTE");
3509 if (symtab && symtab->symbols
3510 && isym < symtab->nsyms
3511 && symtab->symbols[isym].symbol.name)
3512 fprintf (file, " %s", symtab->symbols[isym].symbol.name);
3513 fprintf (file, "\n");
3514 }
3515 break;
3516 default:
3517 break;
3518 }
3519 }
3520 }
3521 if (dysymtab->nextrefsyms > 0)
3522 {
3523 bfd_mach_o_symtab_command *symtab = mdata->symtab;
3524
3525 fprintf (file, " external reference table: (symbol flags)\n");
3526 for (i = 0; i < dysymtab->nextrefsyms; i++)
3527 {
3528 bfd_mach_o_dylib_reference *ref = &dysymtab->ext_refs[i];
3529
3530 fprintf (file, " %4u: %5lu 0x%02lx", i, ref->isym, ref->flags);
3531 if (symtab && symtab->symbols
3532 && ref->isym < symtab->nsyms
3533 && symtab->symbols[ref->isym].symbol.name)
3534 fprintf (file, " %s", symtab->symbols[ref->isym].symbol.name);
3535 fprintf (file, "\n");
3536 }
3537 }
3538
3539}
3540
3541bfd_boolean
3542bfd_mach_o_bfd_print_private_bfd_data (bfd *abfd, PTR ptr)
3543{
3544 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3545 FILE *file = (FILE *) ptr;
3546 unsigned int i;
3547
3548 bfd_mach_o_print_private_header (abfd, file);
3549 fputc ('\n', file);
15e1c58a
TG
3550
3551 for (i = 0; i < mdata->header.ncmds; i++)
3552 {
3553 bfd_mach_o_load_command *cmd = &mdata->commands[i];
046b007d
TG
3554
3555 fprintf (file, "Load command %s:",
3556 bfd_mach_o_get_name (bfd_mach_o_load_command_name, cmd->type));
15e1c58a
TG
3557 switch (cmd->type)
3558 {
3559 case BFD_MACH_O_LC_SEGMENT:
3560 case BFD_MACH_O_LC_SEGMENT_64:
046b007d 3561 bfd_mach_o_print_segment (abfd, cmd, file);
15e1c58a
TG
3562 break;
3563 case BFD_MACH_O_LC_UUID:
3564 {
3565 bfd_mach_o_uuid_command *uuid = &cmd->command.uuid;
3566 unsigned int i;
3567
15e1c58a
TG
3568 for (i = 0; i < sizeof (uuid->uuid); i++)
3569 fprintf (file, " %02x", uuid->uuid[i]);
3570 fputc ('\n', file);
3571 }
3572 break;
3573 case BFD_MACH_O_LC_LOAD_DYLIB:
046b007d
TG
3574 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
3575 case BFD_MACH_O_LC_REEXPORT_DYLIB:
3576 case BFD_MACH_O_LC_ID_DYLIB:
15e1c58a
TG
3577 {
3578 bfd_mach_o_dylib_command *dylib = &cmd->command.dylib;
b32e07d7 3579 fprintf (file, " %s\n", dylib->name_str);
15e1c58a
TG
3580 fprintf (file, " time stamp: 0x%08lx\n",
3581 dylib->timestamp);
3582 fprintf (file, " current version: 0x%08lx\n",
3583 dylib->current_version);
3584 fprintf (file, " comptibility version: 0x%08lx\n",
3585 dylib->compatibility_version);
15e1c58a
TG
3586 break;
3587 }
3588 case BFD_MACH_O_LC_LOAD_DYLINKER:
b32e07d7
TG
3589 case BFD_MACH_O_LC_ID_DYLINKER:
3590 fprintf (file, " %s\n", cmd->command.dylinker.name_str);
3591 break;
15e1c58a
TG
3592 case BFD_MACH_O_LC_SYMTAB:
3593 {
3594 bfd_mach_o_symtab_command *symtab = &cmd->command.symtab;
15e1c58a 3595 fprintf (file,
046b007d
TG
3596 "\n"
3597 " symoff: 0x%08x nsyms: %8u (endoff: 0x%08x)\n",
3598 symtab->symoff, symtab->nsyms,
3599 symtab->symoff + symtab->nsyms
3600 * (mach_o_wide_p (&mdata->header)
3601 ? BFD_MACH_O_NLIST_64_SIZE : BFD_MACH_O_NLIST_SIZE));
15e1c58a 3602 fprintf (file,
046b007d
TG
3603 " stroff: 0x%08x strsize: %8u (endoff: 0x%08x)\n",
3604 symtab->stroff, symtab->strsize,
3605 symtab->stroff + symtab->strsize);
15e1c58a
TG
3606 break;
3607 }
046b007d
TG
3608 case BFD_MACH_O_LC_DYSYMTAB:
3609 fprintf (file, "\n");
3610 bfd_mach_o_print_dysymtab (abfd, cmd, file);
3611 break;
3612 case BFD_MACH_O_LC_CODE_SIGNATURE:
3613 case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO:
3614 {
3615 bfd_mach_o_linkedit_command *linkedit = &cmd->command.linkedit;
3616 fprintf
3617 (file, "\n"
3618 " dataoff: 0x%08lx datasize: 0x%08lx (endoff: 0x%08lx)\n",
3619 linkedit->dataoff, linkedit->datasize,
3620 linkedit->dataoff + linkedit->datasize);
3621 break;
3622 }
3623 case BFD_MACH_O_LC_SUB_FRAMEWORK:
3624 case BFD_MACH_O_LC_SUB_UMBRELLA:
3625 case BFD_MACH_O_LC_SUB_LIBRARY:
3626 case BFD_MACH_O_LC_SUB_CLIENT:
3627 {
3628 bfd_mach_o_str_command *str = &cmd->command.str;
3629 fprintf (file, " %s\n", str->str);
3630 break;
3631 }
b32e07d7
TG
3632 case BFD_MACH_O_LC_THREAD:
3633 case BFD_MACH_O_LC_UNIXTHREAD:
3634 {
3635 bfd_mach_o_thread_command *thread = &cmd->command.thread;
3636 unsigned int j;
3637 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
3638
3639 fprintf (file, " nflavours: %lu\n", thread->nflavours);
3640 for (j = 0; j < thread->nflavours; j++)
3641 {
3642 bfd_mach_o_thread_flavour *flavour = &thread->flavours[j];
3643
3644 fprintf (file, " %2u: flavour: 0x%08lx offset: 0x%08lx"
3645 " size: 0x%08lx\n",
3646 j, flavour->flavour, flavour->offset,
3647 flavour->size);
3648 if (bed->_bfd_mach_o_print_thread)
3649 {
3650 char *buf = bfd_malloc (flavour->size);
3651
3652 if (buf
3653 && bfd_seek (abfd, flavour->offset, SEEK_SET) == 0
3654 && (bfd_bread (buf, flavour->size, abfd)
3655 == flavour->size))
3656 (*bed->_bfd_mach_o_print_thread)(abfd, flavour,
3657 file, buf);
3658 free (buf);
3659 }
3660 }
3661 break;
3662 }
15e1c58a 3663 default:
046b007d 3664 fprintf (file, "\n");
15e1c58a
TG
3665 break;
3666 }
046b007d 3667 fputc ('\n', file);
15e1c58a
TG
3668 }
3669
046b007d
TG
3670 bfd_mach_o_print_section_map (abfd, file);
3671
15e1c58a
TG
3672 return TRUE;
3673}
3674
3af9a47b 3675int
116c20d2
NC
3676bfd_mach_o_core_fetch_environment (bfd *abfd,
3677 unsigned char **rbuf,
3678 unsigned int *rlen)
3af9a47b 3679{
046b007d 3680 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
3af9a47b
NC
3681 unsigned long stackaddr = bfd_mach_o_stack_addr (mdata->header.cputype);
3682 unsigned int i = 0;
3683
3684 for (i = 0; i < mdata->header.ncmds; i++)
3685 {
3686 bfd_mach_o_load_command *cur = &mdata->commands[i];
3687 bfd_mach_o_segment_command *seg = NULL;
3688
3689 if (cur->type != BFD_MACH_O_LC_SEGMENT)
3690 continue;
3691
3692 seg = &cur->command.segment;
3693
3694 if ((seg->vmaddr + seg->vmsize) == stackaddr)
3695 {
3696 unsigned long start = seg->fileoff;
3697 unsigned long end = seg->fileoff + seg->filesize;
3698 unsigned char *buf = bfd_malloc (1024);
3699 unsigned long size = 1024;
3700
3701 for (;;)
3702 {
3703 bfd_size_type nread = 0;
3704 unsigned long offset;
3705 int found_nonnull = 0;
3706
3707 if (size > (end - start))
3708 size = (end - start);
3709
515ef31d
NC
3710 buf = bfd_realloc_or_free (buf, size);
3711 if (buf == NULL)
3712 return -1;
c2f09c75
TG
3713
3714 if (bfd_seek (abfd, end - size, SEEK_SET) != 0)
3715 {
3716 free (buf);
3717 return -1;
3718 }
3719
3af9a47b 3720 nread = bfd_bread (buf, size, abfd);
a95a4550 3721
3af9a47b 3722 if (nread != size)
515ef31d
NC
3723 {
3724 free (buf);
3725 return -1;
3726 }
a95a4550 3727
3af9a47b
NC
3728 for (offset = 4; offset <= size; offset += 4)
3729 {
e84d6fca 3730 unsigned long val;
3af9a47b 3731
e84d6fca 3732 val = *((unsigned long *) (buf + size - offset));
3af9a47b
NC
3733 if (! found_nonnull)
3734 {
3735 if (val != 0)
3736 found_nonnull = 1;
3737 }
3738 else if (val == 0x0)
3739 {
e84d6fca
AM
3740 unsigned long bottom;
3741 unsigned long top;
3af9a47b 3742
e84d6fca
AM
3743 bottom = seg->fileoff + seg->filesize - offset;
3744 top = seg->fileoff + seg->filesize - 4;
3af9a47b
NC
3745 *rbuf = bfd_malloc (top - bottom);
3746 *rlen = top - bottom;
3747
3748 memcpy (*rbuf, buf + size - *rlen, *rlen);
515ef31d 3749 free (buf);
3af9a47b
NC
3750 return 0;
3751 }
3752 }
3753
3754 if (size == (end - start))
3755 break;
3756
3757 size *= 2;
3758 }
515ef31d
NC
3759
3760 free (buf);
3af9a47b
NC
3761 }
3762 }
3763
3764 return -1;
3765}
3766
3767char *
116c20d2 3768bfd_mach_o_core_file_failing_command (bfd *abfd)
3af9a47b
NC
3769{
3770 unsigned char *buf = NULL;
3771 unsigned int len = 0;
3772 int ret = -1;
3773
3774 ret = bfd_mach_o_core_fetch_environment (abfd, &buf, &len);
3775 if (ret < 0)
3776 return NULL;
3777
f075ee0c 3778 return (char *) buf;
3af9a47b
NC
3779}
3780
3781int
116c20d2 3782bfd_mach_o_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
3af9a47b
NC
3783{
3784 return 0;
3785}
3786
92bc0e80
TG
3787#define bfd_mach_o_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
3788#define bfd_mach_o_bfd_reloc_name_lookup _bfd_norelocs_bfd_reloc_name_lookup
3789
3790#define bfd_mach_o_swap_reloc_in NULL
3791#define bfd_mach_o_swap_reloc_out NULL
b32e07d7 3792#define bfd_mach_o_print_thread NULL
92bc0e80 3793
116c20d2
NC
3794#define TARGET_NAME mach_o_be_vec
3795#define TARGET_STRING "mach-o-be"
3796#define TARGET_BIG_ENDIAN 1
3797#define TARGET_ARCHIVE 0
3af9a47b
NC
3798#include "mach-o-target.c"
3799
3800#undef TARGET_NAME
3801#undef TARGET_STRING
3802#undef TARGET_BIG_ENDIAN
3803#undef TARGET_ARCHIVE
3804
116c20d2
NC
3805#define TARGET_NAME mach_o_le_vec
3806#define TARGET_STRING "mach-o-le"
3807#define TARGET_BIG_ENDIAN 0
3808#define TARGET_ARCHIVE 0
3af9a47b
NC
3809
3810#include "mach-o-target.c"
3811
3812#undef TARGET_NAME
3813#undef TARGET_STRING
3814#undef TARGET_BIG_ENDIAN
3815#undef TARGET_ARCHIVE
3816
116c20d2
NC
3817#define TARGET_NAME mach_o_fat_vec
3818#define TARGET_STRING "mach-o-fat"
3819#define TARGET_BIG_ENDIAN 1
3820#define TARGET_ARCHIVE 1
3af9a47b
NC
3821
3822#include "mach-o-target.c"
3823
3824#undef TARGET_NAME
3825#undef TARGET_STRING
3826#undef TARGET_BIG_ENDIAN
3827#undef TARGET_ARCHIVE
This page took 0.555374 seconds and 4 git commands to generate.