diff options
-rw-r--r-- | bfd/ChangeLog | 120 | ||||
-rw-r--r-- | bfd/config.bfd | 4 | ||||
-rwxr-xr-x | bfd/configure | 1 | ||||
-rw-r--r-- | bfd/configure.in | 1 | ||||
-rw-r--r-- | bfd/mach-o-i386.c | 69 | ||||
-rw-r--r-- | bfd/mach-o-target.c | 54 | ||||
-rw-r--r-- | bfd/mach-o.c | 656 | ||||
-rw-r--r-- | bfd/mach-o.h | 84 | ||||
-rw-r--r-- | bfd/targets.c | 2 |
9 files changed, 710 insertions, 281 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 6f8f3ea..34bb1f8 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,117 @@ +2009-06-05 Tristan Gingold <gingold@adacore.com> + + * mach-o.h: Update copyright year. + (bfd_mach_o_mach_header_magic): New enum. + (bfd_mach_o_cpu_subtype): Now an enum. + (BFD_MACH_O_HEADER_SIZE, BFD_MACH_O_HEADER_64_SIZE): New macros. + (BFD_MACH_O_SECTION_SIZE, BFD_MACH_O_SECTION_64_SIZE): Ditto. + (BFD_MACH_O_LC_SEGMENT_SIZE, BFD_MACH_O_LC_SEGMENT_64_SIZE): Ditto. + (bfd_mach_o_load_command): Field type_required is now a boolean. + Reindent prototypes. + (bfd_mach_o_object_p, bfd_mach_o_core_p): Remove. + (bfd_mach_o_bfd_copy_private_symbol_data): Add a prototype. + (bfd_mach_o_bfd_copy_private_section_data): Ditto. + (bfd_mach_o_bfd_copy_private_bfd_data): Ditto. + (bfd_mach_o_get_symtab_upper_bound): Ditto. + (bfd_mach_o_canonicalize_symtab): Ditto. + (bfd_mach_o_get_symbol_info): Ditto. + (bfd_mach_o_print_symbol): Ditto. + (bfd_mach_o_bfd_print_private_bfd_data): Ditto. + (bfd_mach_o_make_empty_symbol): Ditto. + (bfd_mach_o_write_contents): Ditto. + + * mach-o.c (bfd_mach_o_object_p, bfd_mach_o_core_p, + bfd_mach_o_mkobject): Defines. + (bfd_mach_o_valid): Returns FALSE/TRUE instead of 0/1. + Do not check with target vector but with flavour. + (struct mach_o_section_name_xlat): New declaration. + (dwarf_section_names_xlat): Ditto. + (text_section_names_xlat): Ditto. + (data_section_names_xlat): Ditto. + (struct mach_o_segment_name_xlat): Ditto. + (segsec_names_xlat): Ditto. + (bfd_mach_o_convert_section_name_to_bfd): New function. + (bfd_mach_o_convert_section_name_to_mach_o): Ditto. + (bfd_mach_o_bfd_copy_private_symbol_data): Make it public. + (bfd_mach_o_bfd_copy_private_section_data): Ditto. + (bfd_mach_o_bfd_copy_private_bfd_data): Ditto. + Accept any input and output flavour. Do not share private data + anymore. + (bfd_mach_o_count_symbols): Add a comment. + (bfd_mach_o_get_symtab_upper_bound): Make it public. + (bfd_mach_o_canonicalize_symtab): Ditto. + (bfd_mach_o_get_symbol_info): Ditto. + (bfd_mach_o_print_symbol): Ditto. + (bfd_mach_o_write_header): Now returns a boolean instead of an int. + Use constants instead of hard-coded values. + (bfd_mach_o_scan_write_section_32): Use constants instead of hard-coded + values. + (bfd_mach_o_scan_write_section_64): Ditto. + (bfd_mach_o_scan_write_segment): Ditto. + Do not copy sections anymore. + (bfd_mach_o_write_contents): Make it public. + Remove dead code. Rewrite typeflag assignment. + (bfd_mach_o_build_commands): New function. + (bfd_mach_o_set_section_contents): Ditto. + (bfd_mach_o_make_empty_symbol): Make it public. + (bfd_mach_o_read_header): Make it static. + Convert to bfd_boolean. + Use constants instead of hard-coded values. + (bfd_mach_o_make_bfd_section): Call + bfd_mach_o_convert_section_name_to_bfd to create name. + (bfd_mach_o_scan_read_section_32): Use constants instead of hard-coded + values. + (bfd_mach_o_scan_read_section_64): Ditto. + (bfd_mach_o_scan_read_segment): Do not create a bfd section for + a segment anymore. Use constants instead of hard-coded values. + (bfd_mach_o_scan_read_command): Fix style. + (bfd_mach_o_scan): Use constants instead of hard-coded values. + Get rid of BFD_IO_FUNCS. + (bfd_mach_o_mkobject_init): Renamed from bfd_mach_o_mkobject. + (bfd_mach_o_header_p): Created from bfd_mach_o_object_p. + (bfd_mach_o_gen_object_p): New function, replaces bfd_mach_o_object_p. + (bfd_mach_o_object_p): Removed. + (bfd_mach_o_gen_core_p): New function, replaces ... + (bfd_mach_o_core_p): ... deleted. + (bfd_mach_o_bfd_print_private_bfd_data): Make it public. + + * mach-o-i386.c: New file. + * config.bfd: Use mach_o_i386_vec as targ_defvec for ix86-darwin. + * configure.in (TDEFINES): Add mach_o_i386_vec. + * configure: Regenerated. + * targets.c: Add mach_o_i386_vec. + + * mach-o.c: Update copyright years. + (BFD_IO_FUNCS): Remove (was not used). + (bfd_mach_o_mkarchive, bfd_mach_o_read_ar_hdr, bfd_mach_o_slurp_armap + bfd_mach_o_slurp_extended_name_table, + bfd_mach_o_construct_extended_name_table, + bfd_mach_o_truncate_arname, bfd_mach_o_write_armap, + bfd_mach_o_get_elt_at_index, bfd_mach_o_generic_stat_arch_elt, + bfd_mach_o_update_armap_timestamp, bfd_mach_o_close_and_cleanup, + bfd_mach_o_bfd_free_cached_info, bfd_mach_o_new_section_hook, + bfd_mach_o_get_section_contents_in_window, + bfd_mach_o_bfd_is_local_label_name, + bfd_mach_o_bfd_is_target_special_symbol, + bfd_mach_o_bfd_is_local_label_name, bfd_mach_o_get_lineno, + bfd_mach_o_find_nearest_line, bfd_mach_o_find_inliner_info, + bfd_mach_o_bfd_make_debug_symbol, bfd_mach_o_read_minisymbols, + bfd_mach_o_minisymbol_to_symbol, + bfd_mach_o_bfd_get_relocated_section_contents, + bfd_mach_o_bfd_relax_section, bfd_mach_o_bfd_link_hash_table_create, + bfd_mach_o_bfd_link_hash_table_free, bfd_mach_o_bfd_link_add_symbols, + bfd_mach_o_bfd_link_just_syms, bfd_mach_o_bfd_final_link, + bfd_mach_o_bfd_link_split_section, bfd_mach_o_set_arch_mach, + bfd_mach_o_bfd_merge_private_bfd_data, + bfd_mach_o_bfd_set_private_flags, bfd_mach_o_get_section_contents, + bfd_mach_o_bfd_gc_sections, bfd_mach_o_bfd_merge_sections, + bfd_mach_o_bfd_is_group_section, bfd_mach_o_bfd_discard_group, + bfd_mach_o_section_already_linked, bfd_mach_o_bfd_define_common_symbol, + bfd_mach_o_bfd_copy_private_header_data, + bfd_mach_o_core_file_matches_executable_p): Move these defines ... + * mach-o-target.c: ... here. + Update copyright years. + 2009-06-04 Alan Modra <amodra@bigpond.net.au> * dep-in.sed: Don't use \n in replacement part of s command. @@ -564,7 +678,7 @@ 2009-04-21 H.J. Lu <hongjiu.lu@intel.com> * coff-ia64.c (COFF_PAGE_SIZE): Changed to 8K. - + * coffcode.h (coff_compute_section_file_positions): Clear D_PAGED if PE section alignment is smaller than COFF_PAGE_SIZE. @@ -817,7 +931,7 @@ 2009-04-02 Sterling Augustine <sterling@jaw.hq.tensilica.com> - * elf32-xtensa.c (relax_property_section): Always set r_offset + * elf32-xtensa.c (relax_property_section): Always set r_offset to zero. 2009-04-02 Christophe Lyon <christophe.lyon@st.com> @@ -833,7 +947,7 @@ * elf32-vax.c (elf_vax_check_relocs): Do not put relocations against hidden symbols into the GOT or PLT.GOT. - (elf_vax_relocate_section): Do not emit a PCREL reloc + (elf_vax_relocate_section): Do not emit a PCREL reloc into a shared object if it is against a hidden symbol. 2009-04-01 Richard Sandiford <r.sandiford@uk.ibm.com> diff --git a/bfd/config.bfd b/bfd/config.bfd index 545d848..0d042d7 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -541,8 +541,8 @@ case "${targ}" in targ_selvecs="i386coff_vec i386aout_vec" ;; i[3-7]86-*-darwin* | i[3-7]86-*-macos10* | i[3-7]86-*-rhapsody*) - targ_defvec=mach_o_le_vec - targ_selvecs="mach_o_le_vec mach_o_be_vec mach_o_fat_vec pef_vec pef_xlib_vec sym_vec" + targ_defvec=mach_o_i386_vec + targ_selvecs="mach_o_i386_vec mach_o_le_vec mach_o_be_vec mach_o_fat_vec pef_vec pef_xlib_vec sym_vec" targ_archs="bfd_i386_arch bfd_powerpc_arch bfd_rs6000_arch" ;; i[3-7]86-sequent-bsd*) diff --git a/bfd/configure b/bfd/configure index 32f7713..0e3a02a 100755 --- a/bfd/configure +++ b/bfd/configure @@ -21171,6 +21171,7 @@ do mach_o_be_vec) tb="$tb mach-o.lo" ;; mach_o_le_vec) tb="$tb mach-o.lo" ;; mach_o_fat_vec) tb="$tb mach-o.lo" ;; + mach_o_i386_vec) tb="$tb mach-o-i386.lo" ;; mcore_pe_big_vec) tb="$tb pe-mcore.lo peigen.lo cofflink.lo" ;; mcore_pe_little_vec) tb="$tb pe-mcore.lo peigen.lo cofflink.lo" ;; mcore_pei_big_vec) tb="$tb pei-mcore.lo peigen.lo cofflink.lo" ;; diff --git a/bfd/configure.in b/bfd/configure.in index 00c339a..0b446e2 100644 --- a/bfd/configure.in +++ b/bfd/configure.in @@ -868,6 +868,7 @@ do mach_o_be_vec) tb="$tb mach-o.lo" ;; mach_o_le_vec) tb="$tb mach-o.lo" ;; mach_o_fat_vec) tb="$tb mach-o.lo" ;; + mach_o_i386_vec) tb="$tb mach-o-i386.lo" ;; mcore_pe_big_vec) tb="$tb pe-mcore.lo peigen.lo cofflink.lo" ;; mcore_pe_little_vec) tb="$tb pe-mcore.lo peigen.lo cofflink.lo" ;; mcore_pei_big_vec) tb="$tb pei-mcore.lo peigen.lo cofflink.lo" ;; diff --git a/bfd/mach-o-i386.c b/bfd/mach-o-i386.c new file mode 100644 index 0000000..60a6a6f --- /dev/null +++ b/bfd/mach-o-i386.c @@ -0,0 +1,69 @@ +/* Intel i386 Mach-O support for BFD. + Copyright 2009 + Free Software Foundation, Inc. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "sysdep.h" +#include "mach-o.h" +#include "bfd.h" +#include "libbfd.h" +#include "libiberty.h" + +#define bfd_mach_o_object_p bfd_mach_o_i386_object_p +#define bfd_mach_o_core_p bfd_mach_o_i386_core_p +#define bfd_mach_o_mkobject bfd_mach_o_i386_mkobject + +static const bfd_target * +bfd_mach_o_i386_object_p (bfd *abfd) +{ + return bfd_mach_o_header_p (abfd, 0, BFD_MACH_O_CPU_TYPE_I386); +} + +static const bfd_target * +bfd_mach_o_i386_core_p (bfd *abfd) +{ + return bfd_mach_o_header_p (abfd, + BFD_MACH_O_MH_CORE, BFD_MACH_O_CPU_TYPE_I386); +} + +static bfd_boolean +bfd_mach_o_i386_mkobject (bfd *abfd) +{ + bfd_mach_o_data_struct *mdata; + + if (!bfd_mach_o_mkobject_init (abfd)) + return FALSE; + + mdata = abfd->tdata.mach_o_data; + mdata->header.magic = BFD_MACH_O_MH_MAGIC; + mdata->header.cputype = BFD_MACH_O_CPU_TYPE_I386; + mdata->header.cpusubtype = BFD_MACH_O_CPU_SUBTYPE_X86_ALL; + mdata->header.filetype = BFD_MACH_O_MH_OBJECT; + mdata->header.byteorder = BFD_ENDIAN_LITTLE; + mdata->header.version = 1; + + return TRUE; +} + +#define TARGET_NAME mach_o_i386_vec +#define TARGET_STRING "mach-o-i386" +#define TARGET_BIG_ENDIAN 0 +#define TARGET_ARCHIVE 0 + +#include "mach-o-target.c" diff --git a/bfd/mach-o-target.c b/bfd/mach-o-target.c index a435e6e..bf68f93 100644 --- a/bfd/mach-o-target.c +++ b/bfd/mach-o-target.c @@ -1,5 +1,5 @@ /* Mach-O support for BFD. - Copyright 1999, 2000, 2001, 2002, 2007 + Copyright 1999, 2000, 2001, 2002, 2007, 2009 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -19,6 +19,58 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ +/* Define generic entry points here so that we don't need to duplicate the + defines in every target. But define once as this file may be included + several times. */ +#ifndef MACH_O_TARGET_COMMON_DEFINED +#define MACH_O_TARGET_COMMON_DEFINED + +#define bfd_mach_o_mkarchive _bfd_noarchive_mkarchive +#define bfd_mach_o_read_ar_hdr _bfd_noarchive_read_ar_hdr +#define bfd_mach_o_slurp_armap _bfd_noarchive_slurp_armap +#define bfd_mach_o_slurp_extended_name_table _bfd_noarchive_slurp_extended_name_table +#define bfd_mach_o_construct_extended_name_table _bfd_noarchive_construct_extended_name_table +#define bfd_mach_o_truncate_arname _bfd_noarchive_truncate_arname +#define bfd_mach_o_write_armap _bfd_noarchive_write_armap +#define bfd_mach_o_get_elt_at_index _bfd_noarchive_get_elt_at_index +#define bfd_mach_o_generic_stat_arch_elt _bfd_noarchive_generic_stat_arch_elt +#define bfd_mach_o_update_armap_timestamp _bfd_noarchive_update_armap_timestamp +#define bfd_mach_o_close_and_cleanup _bfd_generic_close_and_cleanup +#define bfd_mach_o_bfd_free_cached_info _bfd_generic_bfd_free_cached_info +#define bfd_mach_o_new_section_hook _bfd_generic_new_section_hook +#define bfd_mach_o_get_section_contents_in_window _bfd_generic_get_section_contents_in_window +#define bfd_mach_o_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name +#define bfd_mach_o_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false) +#define bfd_mach_o_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name +#define bfd_mach_o_get_lineno _bfd_nosymbols_get_lineno +#define bfd_mach_o_find_nearest_line _bfd_nosymbols_find_nearest_line +#define bfd_mach_o_find_inliner_info _bfd_nosymbols_find_inliner_info +#define bfd_mach_o_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol +#define bfd_mach_o_read_minisymbols _bfd_generic_read_minisymbols +#define bfd_mach_o_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol +#define bfd_mach_o_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents +#define bfd_mach_o_bfd_relax_section bfd_generic_relax_section +#define bfd_mach_o_bfd_link_hash_table_create _bfd_generic_link_hash_table_create +#define bfd_mach_o_bfd_link_hash_table_free _bfd_generic_link_hash_table_free +#define bfd_mach_o_bfd_link_add_symbols _bfd_generic_link_add_symbols +#define bfd_mach_o_bfd_link_just_syms _bfd_generic_link_just_syms +#define bfd_mach_o_bfd_final_link _bfd_generic_final_link +#define bfd_mach_o_bfd_link_split_section _bfd_generic_link_split_section +#define bfd_mach_o_set_arch_mach bfd_default_set_arch_mach +#define bfd_mach_o_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data +#define bfd_mach_o_bfd_set_private_flags _bfd_generic_bfd_set_private_flags +#define bfd_mach_o_get_section_contents _bfd_generic_get_section_contents +#define bfd_mach_o_bfd_gc_sections bfd_generic_gc_sections +#define bfd_mach_o_bfd_merge_sections bfd_generic_merge_sections +#define bfd_mach_o_bfd_is_group_section bfd_generic_is_group_section +#define bfd_mach_o_bfd_discard_group bfd_generic_discard_group +#define bfd_mach_o_section_already_linked _bfd_generic_section_already_linked +#define bfd_mach_o_bfd_define_common_symbol bfd_generic_define_common_symbol +#define bfd_mach_o_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data +#define bfd_mach_o_core_file_matches_executable_p generic_core_file_matches_executable_p + +#endif /* MACH_O_TARGET_COMMON_DEFINED */ + #ifndef TARGET_NAME #error TARGET_NAME must be defined #endif /* TARGET_NAME */ diff --git a/bfd/mach-o.c b/bfd/mach-o.c index df15312..86f3dd1 100644 --- a/bfd/mach-o.c +++ b/bfd/mach-o.c @@ -1,5 +1,5 @@ /* Mach-O support for BFD. - Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -27,54 +27,9 @@ #include "aout/stab_gnu.h" #include <ctype.h> -#ifndef BFD_IO_FUNCS -#define BFD_IO_FUNCS 0 -#endif - -#define bfd_mach_o_mkarchive _bfd_noarchive_mkarchive -#define bfd_mach_o_read_ar_hdr _bfd_noarchive_read_ar_hdr -#define bfd_mach_o_slurp_armap _bfd_noarchive_slurp_armap -#define bfd_mach_o_slurp_extended_name_table _bfd_noarchive_slurp_extended_name_table -#define bfd_mach_o_construct_extended_name_table _bfd_noarchive_construct_extended_name_table -#define bfd_mach_o_truncate_arname _bfd_noarchive_truncate_arname -#define bfd_mach_o_write_armap _bfd_noarchive_write_armap -#define bfd_mach_o_get_elt_at_index _bfd_noarchive_get_elt_at_index -#define bfd_mach_o_generic_stat_arch_elt _bfd_noarchive_generic_stat_arch_elt -#define bfd_mach_o_update_armap_timestamp _bfd_noarchive_update_armap_timestamp -#define bfd_mach_o_close_and_cleanup _bfd_generic_close_and_cleanup -#define bfd_mach_o_bfd_free_cached_info _bfd_generic_bfd_free_cached_info -#define bfd_mach_o_new_section_hook _bfd_generic_new_section_hook -#define bfd_mach_o_get_section_contents_in_window _bfd_generic_get_section_contents_in_window -#define bfd_mach_o_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name -#define bfd_mach_o_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false) -#define bfd_mach_o_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name -#define bfd_mach_o_get_lineno _bfd_nosymbols_get_lineno -#define bfd_mach_o_find_nearest_line _bfd_nosymbols_find_nearest_line -#define bfd_mach_o_find_inliner_info _bfd_nosymbols_find_inliner_info -#define bfd_mach_o_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol -#define bfd_mach_o_read_minisymbols _bfd_generic_read_minisymbols -#define bfd_mach_o_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol -#define bfd_mach_o_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents -#define bfd_mach_o_bfd_relax_section bfd_generic_relax_section -#define bfd_mach_o_bfd_link_hash_table_create _bfd_generic_link_hash_table_create -#define bfd_mach_o_bfd_link_hash_table_free _bfd_generic_link_hash_table_free -#define bfd_mach_o_bfd_link_add_symbols _bfd_generic_link_add_symbols -#define bfd_mach_o_bfd_link_just_syms _bfd_generic_link_just_syms -#define bfd_mach_o_bfd_final_link _bfd_generic_final_link -#define bfd_mach_o_bfd_link_split_section _bfd_generic_link_split_section -#define bfd_mach_o_set_arch_mach bfd_default_set_arch_mach -#define bfd_mach_o_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data -#define bfd_mach_o_bfd_set_private_flags _bfd_generic_bfd_set_private_flags -#define bfd_mach_o_get_section_contents _bfd_generic_get_section_contents -#define bfd_mach_o_set_section_contents _bfd_generic_set_section_contents -#define bfd_mach_o_bfd_gc_sections bfd_generic_gc_sections -#define bfd_mach_o_bfd_merge_sections bfd_generic_merge_sections -#define bfd_mach_o_bfd_is_group_section bfd_generic_is_group_section -#define bfd_mach_o_bfd_discard_group bfd_generic_discard_group -#define bfd_mach_o_section_already_linked _bfd_generic_section_already_linked -#define bfd_mach_o_bfd_define_common_symbol bfd_generic_define_common_symbol -#define bfd_mach_o_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data -#define bfd_mach_o_core_file_matches_executable_p generic_core_file_matches_executable_p +#define bfd_mach_o_object_p bfd_mach_o_gen_object_p +#define bfd_mach_o_core_p bfd_mach_o_gen_core_p +#define bfd_mach_o_mkobject bfd_false static unsigned int bfd_mach_o_version (bfd *abfd) @@ -91,22 +46,180 @@ bfd_boolean bfd_mach_o_valid (bfd *abfd) { if (abfd == NULL || abfd->xvec == NULL) - return 0; + return FALSE; - if (! ((abfd->xvec == &mach_o_be_vec) - || (abfd->xvec == &mach_o_le_vec) - || (abfd->xvec == &mach_o_fat_vec))) - return 0; + if (abfd->xvec->flavour != bfd_target_mach_o_flavour) + return FALSE; if (abfd->tdata.mach_o_data == NULL) - return 0; - return 1; + return FALSE; + return TRUE; +} + +/* Tables to translate well known Mach-O segment/section names to bfd + names. Use of canonical names (such as .text or .debug_frame) is required + by gdb. */ + +struct mach_o_section_name_xlat +{ + const char *bfd_name; + const char *mach_o_name; +}; + +static const struct mach_o_section_name_xlat dwarf_section_names_xlat[] = + { + { ".debug_frame", "__debug_frame" }, + { ".debug_info", "__debug_info" }, + { ".debug_abbrev", "__debug_abbrev" }, + { ".debug_aranges", "__debug_aranges" }, + { ".debug_macinfo", "__debug_macinfo" }, + { ".debug_line", "__debug_line" }, + { ".debug_loc", "__debug_loc" }, + { ".debug_pubnames", "__debug_pubnames" }, + { ".debug_pubtypes", "__debug_pubtypes" }, + { ".debug_str", "__debug_str" }, + { ".debug_ranges", "__debug_ranges" }, + { NULL, NULL} + }; + +static const struct mach_o_section_name_xlat text_section_names_xlat[] = + { + { ".text", "__text" }, + { ".cstring", "__cstring" }, + { ".eh_frame", "__eh_frame" }, + { NULL, NULL} + }; + +static const struct mach_o_section_name_xlat data_section_names_xlat[] = + { + { ".data", "__data" }, + { ".bss", "__bss" }, + { NULL, NULL} + }; + +struct mach_o_segment_name_xlat +{ + const char *segname; + const struct mach_o_section_name_xlat *sections; +}; + +static const struct mach_o_segment_name_xlat segsec_names_xlat[] = + { + { "__DWARF", dwarf_section_names_xlat }, + { "__TEXT", text_section_names_xlat }, + { "__DATA", data_section_names_xlat }, + { NULL, NULL } + }; + + +/* Mach-O to bfd names. */ + +static char * +bfd_mach_o_convert_section_name_to_bfd (bfd *abfd, bfd_mach_o_section *section) +{ + const struct mach_o_segment_name_xlat *seg; + char *res; + unsigned int len; + + for (seg = segsec_names_xlat; seg->segname; seg++) + { + if (strcmp (seg->segname, section->segname) == 0) + { + const struct mach_o_section_name_xlat *sec; + + for (sec = seg->sections; sec->mach_o_name; sec++) + { + if (strcmp (sec->mach_o_name, section->sectname) == 0) + { + len = strlen (sec->bfd_name); + res = bfd_alloc (abfd, len + 1); + + if (res == NULL) + return NULL; + strcpy (res, sec->bfd_name); + return res; + } + } + } + } + + len = sizeof ("LC_SEGMENT") - 1 + 1 + + strlen (section->segname) + 1 + + strlen (section->sectname) + 1; + + res = bfd_alloc (abfd, len); + if (res == NULL) + return NULL; + snprintf (res, len, "LC_SEGMENT.%s.%s", section->segname, section->sectname); + return res; +} + +/* Convert a bfd sectio name to a Mach-O segment + section name. */ + +static void +bfd_mach_o_convert_section_name_to_mach_o (bfd *abfd ATTRIBUTE_UNUSED, + asection *sect, + bfd_mach_o_section *section) +{ + const struct mach_o_segment_name_xlat *seg; + const char *name = bfd_get_section_name (abfd, sect); + const char *dot; + unsigned int len; + unsigned int seglen; + unsigned int seclen; + + /* List of well known names. */ + for (seg = segsec_names_xlat; seg->segname; seg++) + { + const struct mach_o_section_name_xlat *sec; + + for (sec = seg->sections; sec->mach_o_name; sec++) + { + if (strcmp (sec->bfd_name, name) == 0) + { + strcpy (section->segname, seg->segname); + strcpy (section->sectname, sec->mach_o_name); + return; + } + } + } + + /* Strip LC_SEGMENT. prefix. */ + if (strncmp (name, "LC_SEGMENT.", 11) == 0) + name += 11; + + /* Find a dot. */ + dot = strchr (name, '.'); + len = strlen (name); + + /* Try to split name into segment and section names. */ + if (dot && dot != name) + { + seglen = dot - name; + seclen = len - (dot + 1 - name); + + if (seglen < 16 && seclen < 16) + { + memcpy (section->segname, name, seglen); + section->segname[seglen] = 0; + memcpy (section->sectname, dot + 1, seclen); + section->sectname[seclen] = 0; + return; + } + } + + if (len > 16) + len = 16; + memcpy (section->segname, name, len); + section->segname[len] = 0; + memcpy (section->sectname, name, len); + section->sectname[len] = 0; } /* Copy any private info we understand from the input symbol to the output symbol. */ -static bfd_boolean +bfd_boolean bfd_mach_o_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED, asymbol *isymbol ATTRIBUTE_UNUSED, bfd *obfd ATTRIBUTE_UNUSED, @@ -118,7 +231,7 @@ bfd_mach_o_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED, /* Copy any private info we understand from the input section to the output section. */ -static bfd_boolean +bfd_boolean bfd_mach_o_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED, asection *isection ATTRIBUTE_UNUSED, bfd *obfd ATTRIBUTE_UNUSED, @@ -130,17 +243,23 @@ bfd_mach_o_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED, /* Copy any private info we understand from the input bfd to the output bfd. */ -static bfd_boolean +bfd_boolean bfd_mach_o_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd) { + if (bfd_get_flavour (ibfd) != bfd_target_mach_o_flavour + || bfd_get_flavour (obfd) != bfd_target_mach_o_flavour) + return TRUE; + BFD_ASSERT (bfd_mach_o_valid (ibfd)); BFD_ASSERT (bfd_mach_o_valid (obfd)); - obfd->tdata.mach_o_data = ibfd->tdata.mach_o_data; - obfd->tdata.mach_o_data->ibfd = ibfd; + /* FIXME: copy commands. */ + return TRUE; } +/* Count the total number of symbols. Traverse all sections. */ + static long bfd_mach_o_count_symbols (bfd *abfd) { @@ -161,7 +280,7 @@ bfd_mach_o_count_symbols (bfd *abfd) return nsyms; } -static long +long bfd_mach_o_get_symtab_upper_bound (bfd *abfd) { long nsyms = bfd_mach_o_count_symbols (abfd); @@ -172,7 +291,7 @@ bfd_mach_o_get_symtab_upper_bound (bfd *abfd) return ((nsyms + 1) * sizeof (asymbol *)); } -static long +long bfd_mach_o_canonicalize_symtab (bfd *abfd, asymbol **alocation) { bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data; @@ -210,7 +329,7 @@ bfd_mach_o_canonicalize_symtab (bfd *abfd, asymbol **alocation) return nsyms; } -static void +void bfd_mach_o_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED, asymbol *symbol, symbol_info *ret) @@ -218,7 +337,7 @@ bfd_mach_o_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED, bfd_symbol_info (symbol, ret); } -static void +void bfd_mach_o_print_symbol (bfd *abfd, PTR afile, asymbol *symbol, @@ -319,13 +438,14 @@ bfd_mach_o_convert_architecture (bfd_mach_o_cpu_type mtype, } } -static int +static bfd_boolean bfd_mach_o_write_header (bfd *abfd, bfd_mach_o_header *header) { unsigned char buf[32]; unsigned int size; - size = (header->version == 2) ? 32 : 28; + size = (header->version == 2) ? + BFD_MACH_O_HEADER_64_SIZE : BFD_MACH_O_HEADER_SIZE; bfd_h_put_32 (abfd, header->magic, buf + 0); bfd_h_put_32 (abfd, header->cputype, buf + 4); @@ -340,9 +460,9 @@ bfd_mach_o_write_header (bfd *abfd, bfd_mach_o_header *header) bfd_seek (abfd, 0, SEEK_SET); if (bfd_bwrite ((PTR) buf, size, abfd) != size) - return -1; + return FALSE; - return 0; + return TRUE; } static int @@ -382,7 +502,7 @@ bfd_mach_o_scan_write_section_32 (bfd *abfd, bfd_mach_o_section *section, bfd_vma offset) { - unsigned char buf[68]; + unsigned char buf[BFD_MACH_O_SECTION_SIZE]; memcpy (buf, section->sectname, 16); memcpy (buf + 16, section->segname, 16); @@ -397,7 +517,8 @@ bfd_mach_o_scan_write_section_32 (bfd *abfd, bfd_h_put_32 (abfd, section->reserved2, buf + 64); bfd_seek (abfd, offset, SEEK_SET); - if (bfd_bwrite ((PTR) buf, 68, abfd) != 68) + if (bfd_bwrite ((PTR) buf, BFD_MACH_O_SECTION_SIZE, abfd) + != BFD_MACH_O_SECTION_SIZE) return -1; return 0; @@ -408,7 +529,7 @@ bfd_mach_o_scan_write_section_64 (bfd *abfd, bfd_mach_o_section *section, bfd_vma offset) { - unsigned char buf[80]; + unsigned char buf[BFD_MACH_O_SECTION_64_SIZE]; memcpy (buf, section->sectname, 16); memcpy (buf + 16, section->segname, 16); @@ -424,7 +545,8 @@ bfd_mach_o_scan_write_section_64 (bfd *abfd, bfd_h_put_32 (abfd, section->reserved3, buf + 76); bfd_seek (abfd, offset, SEEK_SET); - if (bfd_bwrite ((PTR) buf, 80, abfd) != 80) + if (bfd_bwrite ((PTR) buf, BFD_MACH_O_SECTION_64_SIZE, abfd) + != BFD_MACH_O_SECTION_64_SIZE) return -1; return 0; @@ -490,38 +612,15 @@ bfd_mach_o_scan_write_segment (bfd *abfd, return -1; } - { - char buf[1024]; - bfd_vma nbytes = seg->filesize; - bfd_vma curoff = seg->fileoff; - - while (nbytes > 0) - { - bfd_vma thiswrite = nbytes; - - if (thiswrite > 1024) - thiswrite = 1024; - - bfd_seek (abfd, curoff, SEEK_SET); - if (bfd_bread ((PTR) buf, thiswrite, abfd) != thiswrite) - return -1; - - bfd_seek (abfd, curoff, SEEK_SET); - if (bfd_bwrite ((PTR) buf, thiswrite, abfd) != thiswrite) - return -1; - - nbytes -= thiswrite; - curoff += thiswrite; - } - } - for (i = 0; i < seg->nsects; i++) { bfd_vma segoff; if (wide) - segoff = command->offset + 64 + 8 + (i * 80); + segoff = command->offset + BFD_MACH_O_LC_SEGMENT_64_SIZE + + (i * BFD_MACH_O_SECTION_64_SIZE); else - segoff = command->offset + 48 + 8 + (i * 68); + segoff = command->offset + BFD_MACH_O_LC_SEGMENT_SIZE + + (i * BFD_MACH_O_SECTION_SIZE); if (bfd_mach_o_scan_write_section (abfd, &seg->sections[i], segoff, wide) != 0) @@ -606,22 +705,14 @@ bfd_mach_o_scan_write_symtab (bfd *abfd, bfd_mach_o_load_command *command) return 0; } -static bfd_boolean +bfd_boolean bfd_mach_o_write_contents (bfd *abfd) { unsigned int i; - asection *s; - bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data; - /* Write data sections first in case they overlap header data to be - written later. */ - - for (s = abfd->sections; s != (asection *) NULL; s = s->next) - ; - /* Now write header information. */ - if (bfd_mach_o_write_header (abfd, &mdata->header) != 0) + if (!bfd_mach_o_write_header (abfd, &mdata->header)) return FALSE; for (i = 0; i < mdata->header.ncmds; i++) @@ -630,7 +721,7 @@ bfd_mach_o_write_contents (bfd *abfd) bfd_mach_o_load_command *cur = &mdata->commands[i]; unsigned long typeflag; - typeflag = cur->type_required ? cur->type & BFD_MACH_O_LC_REQ_DYLD : cur->type; + typeflag = cur->type | (cur->type_required ? BFD_MACH_O_LC_REQ_DYLD : 0); bfd_h_put_32 (abfd, typeflag, buf); bfd_h_put_32 (abfd, cur->len, buf + 4); @@ -686,7 +777,121 @@ bfd_mach_o_write_contents (bfd *abfd) return TRUE; } -static int +/* Build Mach-O load commands from the sections. */ + +bfd_boolean +bfd_mach_o_build_commands (bfd *abfd) +{ + bfd_mach_o_data_struct *mdata = bfd_get_mach_o_data (abfd); + unsigned int wide = (mdata->header.version == 2); + bfd_mach_o_segment_command *seg; + bfd_mach_o_section *sections; + asection *sec; + file_ptr filepos; + + /* Return now if commands are already built. */ + if (mdata->header.ncmds) + return FALSE; + + /* Very simple version: 1 command (segment) containing all sections. */ + mdata->header.ncmds = 1; + mdata->commands = bfd_alloc (abfd, mdata->header.ncmds + * sizeof (bfd_mach_o_load_command)); + if (mdata->commands == NULL) + return FALSE; + seg = &mdata->commands[0].command.segment; + seg->nsects = bfd_count_sections (abfd); + sections = bfd_alloc (abfd, seg->nsects * sizeof (bfd_mach_o_section)); + if (sections == NULL) + return FALSE; + seg->sections = sections; + + /* Set segment command. */ + if (wide) + { + mdata->commands[0].type = BFD_MACH_O_LC_SEGMENT_64; + mdata->commands[0].offset = BFD_MACH_O_HEADER_64_SIZE; + mdata->commands[0].len = BFD_MACH_O_LC_SEGMENT_64_SIZE + + BFD_MACH_O_SECTION_64_SIZE * seg->nsects; + } + else + { + mdata->commands[0].type = BFD_MACH_O_LC_SEGMENT; + mdata->commands[0].offset = BFD_MACH_O_HEADER_SIZE; + mdata->commands[0].len = BFD_MACH_O_LC_SEGMENT_SIZE + + BFD_MACH_O_SECTION_SIZE * seg->nsects; + } + mdata->commands[0].type_required = FALSE; + mdata->header.sizeofcmds = mdata->commands[0].len; + + filepos = mdata->commands[0].offset + mdata->commands[0].len; + + memset (seg->segname, 0, sizeof (seg->segname)); + seg->vmaddr = 0; + seg->fileoff = filepos; + seg->filesize = 0; + seg->maxprot = BFD_MACH_O_PROT_READ | BFD_MACH_O_PROT_WRITE + | BFD_MACH_O_PROT_EXECUTE; + seg->initprot = seg->maxprot; + seg->flags = 0; + + /* Create Mach-O sections. */ + for (sec = abfd->sections; sec; sec = sec->next) + { + sections->bfdsection = sec; + bfd_mach_o_convert_section_name_to_mach_o (abfd, sec, sections); + sections->addr = bfd_get_section_vma (abfd, sec); + sections->size = bfd_get_section_size (sec); + sections->align = bfd_get_section_alignment (abfd, sec); + + filepos = (filepos + ((file_ptr) 1 << sections->align) - 1) + & ((file_ptr) -1 << sections->align); + sections->offset = filepos; + sections->reloff = 0; + sections->nreloc = 0; + sections->reserved1 = 0; + sections->reserved2 = 0; + sections->reserved3 = 0; + + sec->filepos = filepos; + + filepos += sections->size; + sections++; + } + seg->filesize = filepos - seg->fileoff; + seg->vmsize = seg->filesize; + + return TRUE; +} + +/* Set the contents of a section. */ + +bfd_boolean +bfd_mach_o_set_section_contents (bfd *abfd, + asection *section, + const void * location, + file_ptr offset, + bfd_size_type count) +{ + file_ptr pos; + + /* This must be done first, because bfd_set_section_contents is + going to set output_has_begun to TRUE. */ + if (! abfd->output_has_begun && ! bfd_mach_o_build_commands (abfd)) + return FALSE; + + if (count == 0) + return TRUE; + + pos = section->filepos + offset; + if (bfd_seek (abfd, pos, SEEK_SET) != 0 + || bfd_bwrite (location, count, abfd) != count) + return FALSE; + + return TRUE; +} + +int bfd_mach_o_sizeof_headers (bfd *a ATTRIBUTE_UNUSED, struct bfd_link_info *info ATTRIBUTE_UNUSED) { @@ -696,7 +901,7 @@ bfd_mach_o_sizeof_headers (bfd *a ATTRIBUTE_UNUSED, /* Make an empty symbol. This is required only because bfd_make_section_anyway wants to create a symbol for the section. */ -static asymbol * +asymbol * bfd_mach_o_make_empty_symbol (bfd *abfd) { asymbol *new; @@ -708,59 +913,59 @@ bfd_mach_o_make_empty_symbol (bfd *abfd) return new; } -static int +static bfd_boolean bfd_mach_o_read_header (bfd *abfd, bfd_mach_o_header *header) { unsigned char buf[32]; unsigned int size; bfd_vma (*get32) (const void *) = NULL; - bfd_seek (abfd, 0, SEEK_SET); - /* Just read the magic number. */ + bfd_seek (abfd, 0, SEEK_SET); if (bfd_bread ((PTR) buf, 4, abfd) != 4) - return -1; + return FALSE; - if (bfd_getb32 (buf) == 0xfeedface) + if (bfd_getb32 (buf) == BFD_MACH_O_MH_MAGIC) { header->byteorder = BFD_ENDIAN_BIG; - header->magic = 0xfeedface; + header->magic = BFD_MACH_O_MH_MAGIC; header->version = 1; get32 = bfd_getb32; } - else if (bfd_getl32 (buf) == 0xfeedface) + else if (bfd_getl32 (buf) == BFD_MACH_O_MH_MAGIC) { header->byteorder = BFD_ENDIAN_LITTLE; - header->magic = 0xfeedface; + header->magic = BFD_MACH_O_MH_MAGIC; header->version = 1; get32 = bfd_getl32; } - else if (bfd_getb32 (buf) == 0xfeedfacf) + else if (bfd_getb32 (buf) == BFD_MACH_O_MH_MAGIC_64) { header->byteorder = BFD_ENDIAN_BIG; - header->magic = 0xfeedfacf; + header->magic = BFD_MACH_O_MH_MAGIC_64; header->version = 2; get32 = bfd_getb32; } - else if (bfd_getl32 (buf) == 0xfeedfacf) + else if (bfd_getl32 (buf) == BFD_MACH_O_MH_MAGIC_64) { header->byteorder = BFD_ENDIAN_LITTLE; - header->magic = 0xfeedfacf; + header->magic = BFD_MACH_O_MH_MAGIC_64; header->version = 2; get32 = bfd_getl32; } else { header->byteorder = BFD_ENDIAN_UNKNOWN; - return -1; + return FALSE; } /* Once the size of the header is known, read the full header. */ - size = (header->version == 2) ? 32 : 28; + size = (header->version == 2) ? + BFD_MACH_O_HEADER_64_SIZE : BFD_MACH_O_HEADER_SIZE; bfd_seek (abfd, 0, SEEK_SET); if (bfd_bread ((PTR) buf, size, abfd) != size) - return -1; + return FALSE; header->cputype = (*get32) (buf + 4); header->cpusubtype = (*get32) (buf + 8); @@ -772,7 +977,7 @@ bfd_mach_o_read_header (bfd *abfd, bfd_mach_o_header *header) if (header->version == 2) header->reserved = (*get32) (buf + 28); - return 0; + return TRUE; } static asection * @@ -781,41 +986,12 @@ bfd_mach_o_make_bfd_section (bfd *abfd, bfd_mach_o_section *section, { asection *bfdsec; char *sname; - const char *prefix = "LC_SEGMENT"; - unsigned int snamelen; flagword flags; - snamelen = strlen (prefix) + 1 - + strlen (section->segname) + 1 - + strlen (section->sectname) + 1; - - sname = bfd_alloc (abfd, snamelen); + sname = bfd_mach_o_convert_section_name_to_bfd (abfd, section); if (sname == NULL) return NULL; - /* Use canonical dwarf section names for dwarf sections. */ - if (strcmp (section->segname, "__DWARF") == 0 - && strncmp (section->sectname, "__", 2) == 0) - sprintf (sname, ".%s", section->sectname + 2); - else if (strcmp (section->segname, "__TEXT") == 0) - { - if (strcmp (section->sectname, "__eh_frame") == 0) - strcpy (sname, ".eh_frame"); - else if (section->sectname[0]) - sprintf (sname, "%s.%s", section->segname, section->sectname); - else - strcpy (sname, section->segname); - } - else if (strcmp (section->segname, "__DATA") == 0) - { - if (section->sectname[0]) - sprintf (sname, "%s.%s", section->segname, section->sectname); - else - strcpy (sname, section->segname); - } - else - sprintf (sname, "%s.%s.%s", prefix, section->segname, section->sectname); - if (section->flags & BFD_MACH_O_S_ATTR_DEBUG) flags = SEC_HAS_CONTENTS | SEC_DEBUGGING; else @@ -853,10 +1029,11 @@ bfd_mach_o_scan_read_section_32 (bfd *abfd, bfd_vma offset, unsigned long prot) { - unsigned char buf[68]; + unsigned char buf[BFD_MACH_O_SECTION_SIZE]; bfd_seek (abfd, offset, SEEK_SET); - if (bfd_bread ((PTR) buf, 68, abfd) != 68) + if (bfd_bread ((PTR) buf, BFD_MACH_O_SECTION_SIZE, abfd) + != BFD_MACH_O_SECTION_SIZE) return -1; memcpy (section->sectname, buf, 16); @@ -887,10 +1064,11 @@ bfd_mach_o_scan_read_section_64 (bfd *abfd, bfd_vma offset, unsigned long prot) { - unsigned char buf[80]; + unsigned char buf[BFD_MACH_O_SECTION_64_SIZE]; bfd_seek (abfd, offset, SEEK_SET); - if (bfd_bread ((PTR) buf, 80, abfd) != 80) + if (bfd_bread ((PTR) buf, BFD_MACH_O_SECTION_64_SIZE, abfd) + != BFD_MACH_O_SECTION_64_SIZE) return -1; memcpy (section->sectname, buf, 16); @@ -1551,10 +1729,6 @@ bfd_mach_o_scan_read_segment (bfd *abfd, unsigned char buf[64]; bfd_mach_o_segment_command *seg = &command->command.segment; unsigned long i; - asection *bfdsec; - char *sname; - const char *prefix = "LC_SEGMENT"; - unsigned int snamelen; if (wide) { @@ -1597,45 +1771,22 @@ bfd_mach_o_scan_read_segment (bfd *abfd, seg->flags = bfd_h_get_32 (abfd, buf + 44); } - snamelen = strlen (prefix) + 1 + strlen (seg->segname) + 1; - sname = bfd_alloc (abfd, snamelen); - if (sname == NULL) - return -1; - if (strcmp (seg->segname, "__TEXT") == 0 - || strcmp (seg->segname, "__DATA") == 0 - || strcmp (seg->segname, "__IMPORT") == 0 - || strcmp (seg->segname, "__LINKEDIT") == 0) - strcpy (sname, seg->segname); - else - sprintf (sname, "%s.%s", prefix, seg->segname); - - bfdsec = bfd_make_section_anyway (abfd, sname); - if (bfdsec == NULL) - return -1; - - bfdsec->vma = seg->vmaddr; - bfdsec->lma = seg->vmaddr; - bfdsec->size = seg->filesize; - bfdsec->filepos = seg->fileoff; - bfdsec->alignment_power = 0x0; - bfdsec->flags = SEC_HAS_CONTENTS; - bfdsec->segment_mark = 1; - - seg->segment = bfdsec; - if (seg->nsects != 0) { - seg->sections = bfd_alloc (abfd, seg->nsects * sizeof (bfd_mach_o_section)); + seg->sections = bfd_alloc (abfd, seg->nsects + * sizeof (bfd_mach_o_section)); if (seg->sections == NULL) return -1; for (i = 0; i < seg->nsects; i++) { bfd_vma segoff; - if (wide) - segoff = command->offset + 64 + 8 + (i * 80); - else - segoff = command->offset + 48 + 8 + (i * 68); + if (wide) + segoff = command->offset + BFD_MACH_O_LC_SEGMENT_64_SIZE + + (i * BFD_MACH_O_SECTION_64_SIZE); + else + segoff = command->offset + BFD_MACH_O_LC_SEGMENT_SIZE + + (i * BFD_MACH_O_SECTION_SIZE); if (bfd_mach_o_scan_read_section (abfd, &seg->sections[i], segoff, seg->initprot, wide) != 0) @@ -1667,9 +1818,9 @@ bfd_mach_o_scan_read_command (bfd *abfd, bfd_mach_o_load_command *command) if (bfd_bread ((PTR) buf, 8, abfd) != 8) return -1; - command->type = (bfd_h_get_32 (abfd, buf) & ~BFD_MACH_O_LC_REQ_DYLD); + command->type = bfd_h_get_32 (abfd, buf) & ~BFD_MACH_O_LC_REQ_DYLD; command->type_required = (bfd_h_get_32 (abfd, buf) & BFD_MACH_O_LC_REQ_DYLD - ? 1 : 0); + ? TRUE : FALSE); command->len = bfd_h_get_32 (abfd, buf + 4); switch (command->type) @@ -1876,12 +2027,13 @@ bfd_mach_o_scan (bfd *abfd, unsigned long cpusubtype; unsigned int hdrsize; - hdrsize = (header->version == 2) ? 32 : 28; + hdrsize = (header->version == 2) ? + BFD_MACH_O_HEADER_64_SIZE : BFD_MACH_O_HEADER_SIZE; mdata->header = *header; mdata->symbols = NULL; - abfd->flags = abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS); + abfd->flags = abfd->flags & BFD_IN_MEMORY; switch (header->filetype) { case BFD_MACH_O_MH_OBJECT: @@ -1940,7 +2092,7 @@ bfd_mach_o_scan (bfd *abfd, } bfd_boolean -bfd_mach_o_mkobject (bfd *abfd) +bfd_mach_o_mkobject_init (bfd *abfd) { bfd_mach_o_data_struct *mdata = NULL; @@ -1968,13 +2120,15 @@ bfd_mach_o_mkobject (bfd *abfd) } const bfd_target * -bfd_mach_o_object_p (bfd *abfd) +bfd_mach_o_header_p (bfd *abfd, + bfd_mach_o_filetype filetype, + bfd_mach_o_cpu_type cputype) { struct bfd_preserve preserve; bfd_mach_o_header header; preserve.marker = NULL; - if (bfd_mach_o_read_header (abfd, &header) != 0) + if (!bfd_mach_o_read_header (abfd, &header)) goto wrong; if (! (header.byteorder == BFD_ENDIAN_BIG @@ -1993,6 +2147,42 @@ bfd_mach_o_object_p (bfd *abfd) && abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE))) goto wrong; + /* Check cputype and filetype. + In case of wildcard, do not accept magics that are handled by existing + targets. */ + if (cputype) + { + if (header.cputype != cputype) + goto wrong; + } + else + { + switch (header.cputype) + { + case BFD_MACH_O_CPU_TYPE_I386: + /* Handled by mach-o-i386 */ + goto wrong; + default: + break; + } + } + if (filetype) + { + if (header.filetype != filetype) + goto wrong; + } + else + { + switch (header.filetype) + { + case BFD_MACH_O_MH_CORE: + /* Handled by core_p */ + goto wrong; + default: + break; + } + } + preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct)); if (preserve.marker == NULL || !bfd_preserve_save (abfd, &preserve)) @@ -2014,54 +2204,16 @@ bfd_mach_o_object_p (bfd *abfd) return NULL; } -const bfd_target * -bfd_mach_o_core_p (bfd *abfd) +static const bfd_target * +bfd_mach_o_gen_object_p (bfd *abfd) { - struct bfd_preserve preserve; - bfd_mach_o_header header; - - preserve.marker = NULL; - if (bfd_mach_o_read_header (abfd, &header) != 0) - goto wrong; - - if (! (header.byteorder == BFD_ENDIAN_BIG - || header.byteorder == BFD_ENDIAN_LITTLE)) - { - fprintf (stderr, "unknown header byte-order value 0x%lx\n", - (unsigned long) header.byteorder); - abort (); - } - - if (! ((header.byteorder == BFD_ENDIAN_BIG - && abfd->xvec->byteorder == BFD_ENDIAN_BIG - && abfd->xvec->header_byteorder == BFD_ENDIAN_BIG) - || (header.byteorder == BFD_ENDIAN_LITTLE - && abfd->xvec->byteorder == BFD_ENDIAN_LITTLE - && abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE))) - goto wrong; - - if (header.filetype != BFD_MACH_O_MH_CORE) - goto wrong; - - preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct)); - if (preserve.marker == NULL - || !bfd_preserve_save (abfd, &preserve)) - goto fail; - - if (bfd_mach_o_scan (abfd, &header, - (bfd_mach_o_data_struct *) preserve.marker) != 0) - goto wrong; - - bfd_preserve_finish (abfd, &preserve); - return abfd->xvec; - - wrong: - bfd_set_error (bfd_error_wrong_format); + return bfd_mach_o_header_p (abfd, 0, 0); +} - fail: - if (preserve.marker != NULL) - bfd_preserve_restore (abfd, &preserve); - return NULL; +static const bfd_target * +bfd_mach_o_gen_core_p (bfd *abfd) +{ + return bfd_mach_o_header_p (abfd, BFD_MACH_O_MH_CORE, 0); } typedef struct mach_o_fat_archentry @@ -2370,7 +2522,7 @@ bfd_mach_o_stack_addr (enum bfd_mach_o_cpu_type type) } } -static bfd_boolean +bfd_boolean bfd_mach_o_bfd_print_private_bfd_data (bfd *abfd, PTR ptr) { bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data; diff --git a/bfd/mach-o.h b/bfd/mach-o.h index 615a4b3..756fda5 100644 --- a/bfd/mach-o.h +++ b/bfd/mach-o.h @@ -1,5 +1,5 @@ /* Mach-O support for BFD. - Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2008 + Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -40,6 +40,15 @@ #define BFD_MACH_O_SYM_NSECT(SYM) (((SYM)->udata.i >> 16) & 0xff) #define BFD_MACH_O_SYM_NDESC(SYM) ((SYM)->udata.i & 0xffff) +typedef enum bfd_mach_o_mach_header_magic +{ + BFD_MACH_O_MH_MAGIC = 0xfeedface, + BFD_MACH_O_MH_CIGAM = 0xcefaedfe, + BFD_MACH_O_MH_MAGIC_64 = 0xfeedfacf, + BFD_MACH_O_MH_CIGAM_64 = 0xcffaedfe +} +bfd_mach_o_mach_header_magic; + typedef enum bfd_mach_o_ppc_thread_flavour { BFD_MACH_O_PPC_THREAD_STATE = 1, @@ -134,6 +143,12 @@ typedef enum bfd_mach_o_cpu_type } bfd_mach_o_cpu_type; +typedef enum bfd_mach_o_cpu_subtype +{ + BFD_MACH_O_CPU_SUBTYPE_X86_ALL = 3 +} +bfd_mach_o_cpu_subtype; + typedef enum bfd_mach_o_filetype { BFD_MACH_O_MH_OBJECT = 1, @@ -225,8 +240,6 @@ bfd_mach_o_section_type; /* Section contains only true machine instructions. */ #define BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS 0x80000000 -typedef unsigned long bfd_mach_o_cpu_subtype; - typedef struct bfd_mach_o_header { unsigned long magic; @@ -243,6 +256,9 @@ typedef struct bfd_mach_o_header } bfd_mach_o_header; +#define BFD_MACH_O_HEADER_SIZE 28 +#define BFD_MACH_O_HEADER_64_SIZE 32 + typedef struct bfd_mach_o_section { asection *bfdsection; @@ -260,6 +276,8 @@ typedef struct bfd_mach_o_section unsigned long reserved3; } bfd_mach_o_section; +#define BFD_MACH_O_SECTION_SIZE 68 +#define BFD_MACH_O_SECTION_64_SIZE 80 typedef struct bfd_mach_o_segment_command { @@ -276,6 +294,8 @@ typedef struct bfd_mach_o_segment_command asection *segment; } bfd_mach_o_segment_command; +#define BFD_MACH_O_LC_SEGMENT_SIZE 56 +#define BFD_MACH_O_LC_SEGMENT_64_SIZE 72 /* Protection flags. */ #define BFD_MACH_O_PROT_READ 0x01 @@ -506,7 +526,7 @@ bfd_mach_o_uuid_command; typedef struct bfd_mach_o_load_command { bfd_mach_o_load_command_type type; - unsigned int type_required; + bfd_boolean type_required; bfd_vma offset; bfd_vma len; union @@ -540,26 +560,44 @@ mach_o_data_struct; typedef struct mach_o_data_struct bfd_mach_o_data_struct; -bfd_boolean bfd_mach_o_valid (bfd *); -int bfd_mach_o_scan_read_symtab_symbol (bfd *, bfd_mach_o_symtab_command *, asymbol *, unsigned long); -int bfd_mach_o_scan_read_symtab_strtab (bfd *, bfd_mach_o_symtab_command *); -int bfd_mach_o_scan_read_symtab_symbols (bfd *, bfd_mach_o_symtab_command *); -int bfd_mach_o_scan_read_dysymtab_symbol (bfd *, bfd_mach_o_dysymtab_command *, bfd_mach_o_symtab_command *, asymbol *, unsigned long); -int bfd_mach_o_scan_start_address (bfd *); -int bfd_mach_o_scan (bfd *, bfd_mach_o_header *, bfd_mach_o_data_struct *); -bfd_boolean bfd_mach_o_mkobject (bfd *); -const bfd_target * bfd_mach_o_object_p (bfd *); -const bfd_target * bfd_mach_o_core_p (bfd *); -const bfd_target * bfd_mach_o_archive_p (bfd *); -bfd * bfd_mach_o_openr_next_archived_file (bfd *, bfd *); -int bfd_mach_o_lookup_section (bfd *, asection *, bfd_mach_o_load_command **, bfd_mach_o_section **); -int bfd_mach_o_lookup_command (bfd *, bfd_mach_o_load_command_type, bfd_mach_o_load_command **); -unsigned long bfd_mach_o_stack_addr (enum bfd_mach_o_cpu_type); -int bfd_mach_o_core_fetch_environment (bfd *, unsigned char **, unsigned int *); -char * bfd_mach_o_core_file_failing_command (bfd *); -int bfd_mach_o_core_file_failing_signal (bfd *); -bfd_boolean bfd_mach_o_core_file_matches_executable_p (bfd *, bfd *); +bfd_boolean bfd_mach_o_valid (bfd *); +int bfd_mach_o_scan_read_symtab_symbol (bfd *, bfd_mach_o_symtab_command *, asymbol *, unsigned long); +int bfd_mach_o_scan_read_symtab_strtab (bfd *, bfd_mach_o_symtab_command *); +int bfd_mach_o_scan_read_symtab_symbols (bfd *, bfd_mach_o_symtab_command *); +int bfd_mach_o_scan_read_dysymtab_symbol (bfd *, bfd_mach_o_dysymtab_command *, bfd_mach_o_symtab_command *, asymbol *, unsigned long); +int bfd_mach_o_scan_start_address (bfd *); +int bfd_mach_o_scan (bfd *, bfd_mach_o_header *, bfd_mach_o_data_struct *); +bfd_boolean bfd_mach_o_mkobject_init (bfd *); +const bfd_target *bfd_mach_o_object_p (bfd *); +const bfd_target *bfd_mach_o_core_p (bfd *); +const bfd_target *bfd_mach_o_archive_p (bfd *); +bfd *bfd_mach_o_openr_next_archived_file (bfd *, bfd *); +int bfd_mach_o_lookup_section (bfd *, asection *, bfd_mach_o_load_command **, bfd_mach_o_section **); +int bfd_mach_o_lookup_command (bfd *, bfd_mach_o_load_command_type, bfd_mach_o_load_command **); +bfd_boolean bfd_mach_o_write_contents (bfd *); +bfd_boolean bfd_mach_o_bfd_copy_private_symbol_data (bfd *, asymbol *, + bfd *, asymbol *); +bfd_boolean bfd_mach_o_bfd_copy_private_section_data (bfd *, asection *, + bfd *, asection *); +bfd_boolean bfd_mach_o_bfd_copy_private_bfd_data (bfd *, bfd *); +long bfd_mach_o_get_symtab_upper_bound (bfd *); +long bfd_mach_o_canonicalize_symtab (bfd *, asymbol **); +asymbol *bfd_mach_o_make_empty_symbol (bfd *); +void bfd_mach_o_get_symbol_info (bfd *, asymbol *, symbol_info *); +void bfd_mach_o_print_symbol (bfd *, PTR, asymbol *, bfd_print_symbol_type); +bfd_boolean bfd_mach_o_bfd_print_private_bfd_data (bfd *, PTR); +int bfd_mach_o_sizeof_headers (bfd *, struct bfd_link_info *); +unsigned long bfd_mach_o_stack_addr (enum bfd_mach_o_cpu_type); +int bfd_mach_o_core_fetch_environment (bfd *, unsigned char **, unsigned int *); +char *bfd_mach_o_core_file_failing_command (bfd *); +int bfd_mach_o_core_file_failing_signal (bfd *); +bfd_boolean bfd_mach_o_core_file_matches_executable_p (bfd *, bfd *); bfd *bfd_mach_o_fat_extract (bfd *, bfd_format , const bfd_arch_info_type *); +const bfd_target *bfd_mach_o_header_p (bfd *, bfd_mach_o_filetype, + bfd_mach_o_cpu_type); +bfd_boolean bfd_mach_o_build_commands (bfd *abfd); +bfd_boolean bfd_mach_o_set_section_contents (bfd *, asection *, const void *, + file_ptr, bfd_size_type); extern const bfd_target mach_o_be_vec; extern const bfd_target mach_o_le_vec; diff --git a/bfd/targets.c b/bfd/targets.c index 49aa5f1..ba56a44 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -747,6 +747,7 @@ extern const bfd_target m88kopenbsd_vec; extern const bfd_target mach_o_be_vec; extern const bfd_target mach_o_le_vec; extern const bfd_target mach_o_fat_vec; +extern const bfd_target mach_o_i386_vec; extern const bfd_target maxqcoff_vec; extern const bfd_target mcore_pe_big_vec; extern const bfd_target mcore_pe_little_vec; @@ -1115,6 +1116,7 @@ static const bfd_target * const _bfd_target_vector[] = &mach_o_be_vec, &mach_o_le_vec, &mach_o_fat_vec, + &mach_o_i386_vec, &maxqcoff_vec, &mcore_pe_big_vec, &mcore_pe_little_vec, |