diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 26 | ||||
-rw-r--r-- | bfd/Makefile.am | 4 | ||||
-rw-r--r-- | bfd/Makefile.in | 6 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 24 | ||||
-rw-r--r-- | bfd/config.bfd | 11 | ||||
-rwxr-xr-x | bfd/configure | 2 | ||||
-rw-r--r-- | bfd/configure.ac | 2 | ||||
-rw-r--r-- | bfd/libbfd.h | 8 | ||||
-rw-r--r-- | bfd/mach-o-aarch64.c | 308 | ||||
-rw-r--r-- | bfd/mach-o-arm.c | 326 | ||||
-rw-r--r-- | bfd/mach-o-x86-64.c | 4 | ||||
-rw-r--r-- | bfd/reloc.c | 34 | ||||
-rw-r--r-- | bfd/targets.c | 4 |
13 files changed, 741 insertions, 18 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 4f70523..5111d62 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,29 @@ +2015-11-20 Tristan Gingold <gingold@adacore.com> + + * targets.c (aarch64_mach_o_vec, arm_mach_o_vec): Declare. + (_bfd_target_vector): Add new vectors. + * reloc.c (BFD_RELOC_MACH_O_SUBTRACTOR32) + (BFD_RELOC_MACH_O_SUBTRACTOR64, BFD_RELOC_MACH_O_ARM64_ADDEND) + (BFD_RELOC_MACH_O_ARM64_GOT_LOAD_PAGE21) + (BFD_RELOC_MACH_O_ARM64_GOT_LOAD_PAGEOFF12) + (BFD_RELOC_MACH_O_ARM64_POINTER_TO_GOT): New relocations. + (BFD_RELOC_MACH_O_X86_64_SUBTRACTOR32) + (BFD_RELOC_MACH_O_X86_64_SUBTRACTOR64): Remove. + * mach-o-x86-64.c (bfd_mach_o_x86_64_swap_reloc_out): Change + name of subtractor relocations. + * config.bfd: Handle aarch64-*-darwin*, arm-*-darwin*. + * Makefile.am (BFD32_BACKENDS): Add mach-o-arm.lo. + (BFD32_BACKENDS_CFILES): Add mach-o-arm.c. + (BFD64_BACKENDS): Add mach-o-aarch64.lo. + (BFD64_BACKENDS_CFILES): Add mach-o-aarch64.c. + * configure.ac: Handle aarch64_mach_o_vec and arm_mach_o_vec. + * mach-o-aarch64.c: New file. + * mach-o-arm.c: New file. + * Makefile.in: Regenerate. + * bfd-in2.h: Regenerate. + * configure: Regenerate. + * libbfd.h: Regenerate. + 2015-11-20 David Bridgham <dab@froghouse.org> * pdp11.c (TARGET_PAGE_SIZE): Set to 256 to match definition in diff --git a/bfd/Makefile.am b/bfd/Makefile.am index bf73057..cdfed8f 100644 --- a/bfd/Makefile.am +++ b/bfd/Makefile.am @@ -408,6 +408,7 @@ BFD32_BACKENDS = \ m88kopenbsd.lo \ mach-o.lo \ mach-o-i386.lo \ + mach-o-arm.lo \ mipsbsd.lo \ newsos3.lo \ nlm.lo \ @@ -599,6 +600,7 @@ BFD32_BACKENDS_CFILES = \ m88kopenbsd.c \ mach-o.c \ mach-o-i386.c \ + mach-o-arm.c \ mipsbsd.c \ newsos3.c \ nlm.c \ @@ -681,6 +683,7 @@ BFD64_BACKENDS = \ elfn32-mips.lo \ elfxx-ia64.lo \ elfxx-mips.lo \ + mach-o-aarch64.lo \ mach-o-x86-64.lo \ mmo.lo \ nlm32-alpha.lo \ @@ -719,6 +722,7 @@ BFD64_BACKENDS_CFILES = \ elfxx-aarch64.c \ elfxx-ia64.c \ elfxx-mips.c \ + mach-o-aarch64.c \ mach-o-x86-64.c \ mmo.c \ nlm32-alpha.c \ diff --git a/bfd/Makefile.in b/bfd/Makefile.in index 9fd0d68..6cf4b70 100644 --- a/bfd/Makefile.in +++ b/bfd/Makefile.in @@ -712,6 +712,7 @@ BFD32_BACKENDS = \ m88kopenbsd.lo \ mach-o.lo \ mach-o-i386.lo \ + mach-o-arm.lo \ mipsbsd.lo \ newsos3.lo \ nlm.lo \ @@ -903,6 +904,7 @@ BFD32_BACKENDS_CFILES = \ m88kopenbsd.c \ mach-o.c \ mach-o-i386.c \ + mach-o-arm.c \ mipsbsd.c \ newsos3.c \ nlm.c \ @@ -986,6 +988,7 @@ BFD64_BACKENDS = \ elfn32-mips.lo \ elfxx-ia64.lo \ elfxx-mips.lo \ + mach-o-aarch64.lo \ mach-o-x86-64.lo \ mmo.lo \ nlm32-alpha.lo \ @@ -1024,6 +1027,7 @@ BFD64_BACKENDS_CFILES = \ elfxx-aarch64.c \ elfxx-ia64.c \ elfxx-mips.c \ + mach-o-aarch64.c \ mach-o-x86-64.c \ mmo.c \ nlm32-alpha.c \ @@ -1538,6 +1542,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m68knetbsd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m88kmach3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m88kopenbsd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mach-o-aarch64.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mach-o-arm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mach-o-i386.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mach-o-x86-64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mach-o.Plo@am__quote@ diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 3780ba2..db54efe 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -5575,6 +5575,12 @@ BFD_RELOC_MACH_O_PAIR. */ /* Pair of relocation. Contains the first symbol. */ BFD_RELOC_MACH_O_PAIR, +/* Symbol will be substracted. Must be followed by a BFD_RELOC_32. */ + BFD_RELOC_MACH_O_SUBTRACTOR32, + +/* Symbol will be substracted. Must be followed by a BFD_RELOC_64. */ + BFD_RELOC_MACH_O_SUBTRACTOR64, + /* PCREL relocations. They are marked as branch to create PLT entry if required. */ BFD_RELOC_MACH_O_X86_64_BRANCH32, @@ -5587,12 +5593,6 @@ required. */ the linker could optimize the movq to a leaq if possible. */ BFD_RELOC_MACH_O_X86_64_GOT_LOAD, -/* Symbol will be substracted. Must be followed by a BFD_RELOC_64. */ - BFD_RELOC_MACH_O_X86_64_SUBTRACTOR32, - -/* Symbol will be substracted. Must be followed by a BFD_RELOC_64. */ - BFD_RELOC_MACH_O_X86_64_SUBTRACTOR64, - /* Same as BFD_RELOC_32_PCREL but with an implicit -1 addend. */ BFD_RELOC_MACH_O_X86_64_PCREL32_1, @@ -5602,6 +5602,18 @@ the linker could optimize the movq to a leaq if possible. */ /* Same as BFD_RELOC_32_PCREL but with an implicit -4 addend. */ BFD_RELOC_MACH_O_X86_64_PCREL32_4, +/* Addend for PAGE or PAGEOFF. */ + BFD_RELOC_MACH_O_ARM64_ADDEND, + +/* Relative offset to page of GOT slot. */ + BFD_RELOC_MACH_O_ARM64_GOT_LOAD_PAGE21, + +/* Relative offset within page of GOT slot. */ + BFD_RELOC_MACH_O_ARM64_GOT_LOAD_PAGEOFF12, + +/* Address of a GOT entry. */ + BFD_RELOC_MACH_O_ARM64_POINTER_TO_GOT, + /* This is a 32 bit reloc for the microblaze that stores the low 16 bits of a value */ BFD_RELOC_MICROBLAZE_32_LO, diff --git a/bfd/config.bfd b/bfd/config.bfd index c5688cb..462a00d 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -169,6 +169,12 @@ case "${targ}" in # START OF targmatch.h #ifdef BFD64 + aarch64-*-darwin*) + targ_defvec=aarch64_mach_o_vec + targ_selvecs="arm_mach_o_vec mach_o_le_vec mach_o_be_vec mach_o_fat_vec" + targ_archs="$targ_archs bfd_i386_arch bfd_powerpc_arch bfd_rs6000_arch" + want64=true + ;; aarch64-*-elf) targ_defvec=aarch64_elf64_le_vec targ_selvecs="aarch64_elf64_be_vec aarch64_elf32_le_vec aarch64_elf32_be_vec arm_elf32_le_vec arm_elf32_be_vec" @@ -273,6 +279,11 @@ case "${targ}" in targ_selvecs=arc_elf32_be_vec ;; + arm-*-darwin*) + targ_defvec=arm_mach_o_vec + targ_selvecs="mach_o_le_vec mach_o_be_vec mach_o_fat_vec" + targ_archs="$targ_archs bfd_i386_arch bfd_powerpc_arch bfd_rs6000_arch" + ;; arm-*-nacl*) targ_defvec=arm_elf32_nacl_le_vec targ_selvecs="arm_elf32_nacl_be_vec i386_elf32_nacl_vec" diff --git a/bfd/configure b/bfd/configure index 9fe15f6..c8cdcc5 100755 --- a/bfd/configure +++ b/bfd/configure @@ -15253,6 +15253,7 @@ do aarch64_elf64_be_cloudabi_vec) tb="$tb elf64-aarch64.lo elfxx-aarch64.lo elf-ifunc.lo elf64.lo $elf"; target_size=64 ;; aarch64_elf64_le_vec) tb="$tb elf64-aarch64.lo elfxx-aarch64.lo elf-ifunc.lo elf64.lo $elf"; target_size=64 ;; aarch64_elf64_le_cloudabi_vec) tb="$tb elf64-aarch64.lo elfxx-aarch64.lo elf-ifunc.lo elf64.lo $elf"; target_size=64 ;; + aarch64_mach_o_vec) tb="$tb mach-o-aarch64.lo"; target_size=64 ;; alpha_ecoff_le_vec) tb="$tb coff-alpha.lo ecoff.lo $ecoff"; target_size=64 ;; alpha_elf64_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;; alpha_elf64_fbsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;; @@ -15292,6 +15293,7 @@ do arm_pei_epoc_le_vec) tb="$tb epoc-pei-arm.lo peigen.lo $coff" ;; arm_pei_wince_be_vec) tb="$tb pei-arm-wince.lo pei-arm.lo peigen.lo $coff" ;; arm_pei_wince_le_vec) tb="$tb pei-arm-wince.lo pei-arm.lo peigen.lo $coff" ;; + arm_mach_o_vec) tb="$tb mach-o-arm.lo" ;; avr_elf32_vec) tb="$tb elf32-avr.lo elf32.lo $elf" ;; bfin_elf32_vec) tb="$tb elf32-bfin.lo elf32.lo $elf" ;; bfin_elf32_fdpic_vec) tb="$tb elf32-bfin.lo elf32.lo $elf" ;; diff --git a/bfd/configure.ac b/bfd/configure.ac index 6f5e85f..bf76fb1 100644 --- a/bfd/configure.ac +++ b/bfd/configure.ac @@ -699,6 +699,7 @@ do aarch64_elf64_be_cloudabi_vec) tb="$tb elf64-aarch64.lo elfxx-aarch64.lo elf-ifunc.lo elf64.lo $elf"; target_size=64 ;; aarch64_elf64_le_vec) tb="$tb elf64-aarch64.lo elfxx-aarch64.lo elf-ifunc.lo elf64.lo $elf"; target_size=64 ;; aarch64_elf64_le_cloudabi_vec) tb="$tb elf64-aarch64.lo elfxx-aarch64.lo elf-ifunc.lo elf64.lo $elf"; target_size=64 ;; + aarch64_mach_o_vec) tb="$tb mach-o-aarch64.lo"; target_size=64 ;; alpha_ecoff_le_vec) tb="$tb coff-alpha.lo ecoff.lo $ecoff"; target_size=64 ;; alpha_elf64_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;; alpha_elf64_fbsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;; @@ -738,6 +739,7 @@ do arm_pei_epoc_le_vec) tb="$tb epoc-pei-arm.lo peigen.lo $coff" ;; arm_pei_wince_be_vec) tb="$tb pei-arm-wince.lo pei-arm.lo peigen.lo $coff" ;; arm_pei_wince_le_vec) tb="$tb pei-arm-wince.lo pei-arm.lo peigen.lo $coff" ;; + arm_mach_o_vec) tb="$tb mach-o-arm.lo" ;; avr_elf32_vec) tb="$tb elf32-avr.lo elf32.lo $elf" ;; bfin_elf32_vec) tb="$tb elf32-bfin.lo elf32.lo $elf" ;; bfin_elf32_fdpic_vec) tb="$tb elf32-bfin.lo elf32.lo $elf" ;; diff --git a/bfd/libbfd.h b/bfd/libbfd.h index a095d7c..a6ed64e 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -2750,15 +2750,19 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_MACH_O_SECTDIFF", "BFD_RELOC_MACH_O_LOCAL_SECTDIFF", "BFD_RELOC_MACH_O_PAIR", + "BFD_RELOC_MACH_O_SUBTRACTOR32", + "BFD_RELOC_MACH_O_SUBTRACTOR64", "BFD_RELOC_MACH_O_X86_64_BRANCH32", "BFD_RELOC_MACH_O_X86_64_BRANCH8", "BFD_RELOC_MACH_O_X86_64_GOT", "BFD_RELOC_MACH_O_X86_64_GOT_LOAD", - "BFD_RELOC_MACH_O_X86_64_SUBTRACTOR32", - "BFD_RELOC_MACH_O_X86_64_SUBTRACTOR64", "BFD_RELOC_MACH_O_X86_64_PCREL32_1", "BFD_RELOC_MACH_O_X86_64_PCREL32_2", "BFD_RELOC_MACH_O_X86_64_PCREL32_4", + "BFD_RELOC_MACH_O_ARM64_ADDEND", + "BFD_RELOC_MACH_O_ARM64_GOT_LOAD_PAGE21", + "BFD_RELOC_MACH_O_ARM64_GOT_LOAD_PAGEOFF12", + "BFD_RELOC_MACH_O_ARM64_POINTER_TO_GOT", "BFD_RELOC_MICROBLAZE_32_LO", "BFD_RELOC_MICROBLAZE_32_LO_PCREL", "BFD_RELOC_MICROBLAZE_32_ROSDA", diff --git a/bfd/mach-o-aarch64.c b/bfd/mach-o-aarch64.c new file mode 100644 index 0000000..0d3c8ee --- /dev/null +++ b/bfd/mach-o-aarch64.c @@ -0,0 +1,308 @@ +/* AArch-64 Mach-O support for BFD. + Copyright (C) 2015 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" +#include "mach-o/arm64.h" + +#define bfd_mach_o_object_p bfd_mach_o_arm64_object_p +#define bfd_mach_o_core_p bfd_mach_o_arm64_core_p +#define bfd_mach_o_mkobject bfd_mach_o_arm64_mkobject + +#define bfd_mach_o_canonicalize_one_reloc \ + bfd_mach_o_arm64_canonicalize_one_reloc +#define bfd_mach_o_swap_reloc_out NULL + +#define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_arm64_bfd_reloc_type_lookup +#define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_arm64_bfd_reloc_name_lookup + +#define bfd_mach_o_print_thread NULL +#define bfd_mach_o_tgt_seg_table NULL +#define bfd_mach_o_section_type_valid_for_tgt NULL + +static const bfd_target * +bfd_mach_o_arm64_object_p (bfd *abfd) +{ + return bfd_mach_o_header_p (abfd, 0, 0, BFD_MACH_O_CPU_TYPE_ARM64); +} + +static const bfd_target * +bfd_mach_o_arm64_core_p (bfd *abfd) +{ + return bfd_mach_o_header_p (abfd, 0, + BFD_MACH_O_MH_CORE, BFD_MACH_O_CPU_TYPE_ARM64); +} + +static bfd_boolean +bfd_mach_o_arm64_mkobject (bfd *abfd) +{ + bfd_mach_o_data_struct *mdata; + + if (!bfd_mach_o_mkobject_init (abfd)) + return FALSE; + + mdata = bfd_mach_o_get_data (abfd); + mdata->header.magic = BFD_MACH_O_MH_MAGIC; + mdata->header.cputype = BFD_MACH_O_CPU_TYPE_ARM64; + mdata->header.cpusubtype = BFD_MACH_O_CPU_SUBTYPE_ARM64_ALL; + mdata->header.byteorder = BFD_ENDIAN_LITTLE; + mdata->header.version = 1; + + return TRUE; +} + +/* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ +#define MINUS_ONE (~ (bfd_vma) 0) + +static reloc_howto_type arm64_howto_table[]= +{ + /* 0 */ + HOWTO (BFD_RELOC_64, 0, 4, 64, FALSE, 0, + complain_overflow_bitfield, + NULL, "64", + FALSE, MINUS_ONE, MINUS_ONE, FALSE), + HOWTO (BFD_RELOC_32, 0, 2, 32, FALSE, 0, + complain_overflow_bitfield, + NULL, "32", + FALSE, 0xffffffff, 0xffffffff, FALSE), + HOWTO (BFD_RELOC_16, 0, 1, 16, FALSE, 0, + complain_overflow_bitfield, + NULL, "16", + FALSE, 0xffff, 0xffff, FALSE), + HOWTO (BFD_RELOC_8, 0, 0, 8, FALSE, 0, + complain_overflow_bitfield, + NULL, "8", + FALSE, 0xff, 0xff, FALSE), + /* 4 */ + HOWTO (BFD_RELOC_64_PCREL, 0, 4, 64, TRUE, 0, + complain_overflow_bitfield, + NULL, "DISP64", + FALSE, MINUS_ONE, MINUS_ONE, TRUE), + HOWTO (BFD_RELOC_32_PCREL, 0, 2, 32, TRUE, 0, + complain_overflow_bitfield, + NULL, "DISP32", + FALSE, 0xffffffff, 0xffffffff, TRUE), + HOWTO (BFD_RELOC_16_PCREL, 0, 1, 16, TRUE, 0, + complain_overflow_bitfield, + NULL, "DISP16", + FALSE, 0xffff, 0xffff, TRUE), + HOWTO (BFD_RELOC_AARCH64_CALL26, 0, 2, 26, TRUE, 0, + complain_overflow_bitfield, + NULL, "BRANCH26", + FALSE, 0x03ffffff, 0x03ffffff, TRUE), + /* 8 */ + HOWTO (BFD_RELOC_AARCH64_ADR_HI21_PCREL, 12, 2, 21, TRUE, 0, + complain_overflow_signed, + NULL, "PAGE21", + FALSE, 0x1fffff, 0x1fffff, TRUE), + HOWTO (BFD_RELOC_AARCH64_LDST16_LO12, 1, 2, 12, TRUE, 0, + complain_overflow_signed, + NULL, "PGOFF12", + FALSE, 0xffe, 0xffe, TRUE), + HOWTO (BFD_RELOC_MACH_O_ARM64_ADDEND, 0, 2, 32, FALSE, 0, + complain_overflow_signed, + NULL, "ADDEND", + FALSE, 0xffffffff, 0xffffffff, FALSE), + HOWTO (BFD_RELOC_MACH_O_SUBTRACTOR32, 0, 2, 32, FALSE, 0, + complain_overflow_bitfield, + NULL, "SUBTRACTOR32", + FALSE, 0xffffffff, 0xffffffff, FALSE), + /* 12 */ + HOWTO (BFD_RELOC_MACH_O_SUBTRACTOR64, 0, 4, 64, FALSE, 0, + complain_overflow_bitfield, + NULL, "SUBTRACTOR64", + FALSE, MINUS_ONE, MINUS_ONE, FALSE), + HOWTO (BFD_RELOC_MACH_O_ARM64_GOT_LOAD_PAGE21, 12, 2, 21, TRUE, 0, + complain_overflow_signed, + NULL, "GOT_LD_PG21", + FALSE, 0x1fffff, 0x1fffff, TRUE), + HOWTO (BFD_RELOC_MACH_O_ARM64_GOT_LOAD_PAGEOFF12, 1, 2, 12, TRUE, 0, + complain_overflow_signed, + NULL, "GOT_LD_PGOFF12", + FALSE, 0xffe, 0xffe, TRUE), + HOWTO (BFD_RELOC_MACH_O_ARM64_POINTER_TO_GOT, 0, 2, 32, TRUE, 0, + complain_overflow_bitfield, + NULL, "PTR_TO_GOT", + FALSE, 0xffffffff, 0xffffffff, TRUE), +}; + +static bfd_boolean +bfd_mach_o_arm64_canonicalize_one_reloc (bfd *abfd, + struct mach_o_reloc_info_external *raw, + arelent *res, asymbol **syms) +{ + bfd_mach_o_reloc_info reloc; + + res->address = bfd_get_32 (abfd, raw->r_address); + if (res->address & BFD_MACH_O_SR_SCATTERED) + { + /* Only non-scattered relocations. */ + return FALSE; + } + + /* The value and info fields have to be extracted dependent on target + endian-ness. */ + bfd_mach_o_swap_in_non_scattered_reloc (abfd, &reloc, raw->r_symbolnum); + + if (reloc.r_type == BFD_MACH_O_ARM64_RELOC_ADDEND) + { + if (reloc.r_length == 2 && reloc.r_pcrel == 0) + { + res->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; + res->addend = reloc.r_value; + res->howto = &arm64_howto_table[10]; + return TRUE; + } + return FALSE; + } + + if (!bfd_mach_o_canonicalize_non_scattered_reloc (abfd, &reloc, res, syms)) + return FALSE; + + switch (reloc.r_type) + { + case BFD_MACH_O_ARM64_RELOC_UNSIGNED: + switch ((reloc.r_length << 1) | reloc.r_pcrel) + { + case 0: /* len = 0, pcrel = 0 */ + res->howto = &arm64_howto_table[3]; + return TRUE; + case 2: /* len = 1, pcrel = 0 */ + res->howto = &arm64_howto_table[2]; + return TRUE; + case 3: /* len = 1, pcrel = 1 */ + res->howto = &arm64_howto_table[6]; + return TRUE; + case 4: /* len = 2, pcrel = 0 */ + res->howto = &arm64_howto_table[1]; + return TRUE; + case 5: /* len = 2, pcrel = 1 */ + res->howto = &arm64_howto_table[5]; + return TRUE; + case 6: /* len = 3, pcrel = 0 */ + res->howto = &arm64_howto_table[0]; + return TRUE; + case 7: /* len = 3, pcrel = 1 */ + res->howto = &arm64_howto_table[4]; + return TRUE; + default: + return FALSE; + } + break; + case BFD_MACH_O_ARM64_RELOC_SUBTRACTOR: + if (reloc.r_pcrel) + return FALSE; + switch (reloc.r_length) + { + case 2: + res->howto = &arm64_howto_table[11]; + return TRUE; + case 3: + res->howto = &arm64_howto_table[12]; + return TRUE; + default: + return FALSE; + } + break; + case BFD_MACH_O_ARM64_RELOC_BRANCH26: + if (reloc.r_length == 2 && reloc.r_pcrel == 1) + { + res->howto = &arm64_howto_table[7]; + return TRUE; + } + break; + case BFD_MACH_O_ARM64_RELOC_PAGE21: + if (reloc.r_length == 2 && reloc.r_pcrel == 1) + { + res->howto = &arm64_howto_table[8]; + return TRUE; + } + break; + case BFD_MACH_O_ARM64_RELOC_PAGEOFF12: + if (reloc.r_length == 2 && reloc.r_pcrel == 0) + { + res->howto = &arm64_howto_table[9]; + return TRUE; + } + break; + case BFD_MACH_O_ARM64_RELOC_GOT_LOAD_PAGE21: + if (reloc.r_length == 2 && reloc.r_pcrel == 1) + { + res->howto = &arm64_howto_table[13]; + return TRUE; + } + break; + case BFD_MACH_O_ARM64_RELOC_GOT_LOAD_PAGEOFF12: + if (reloc.r_length == 2 && reloc.r_pcrel == 0) + { + res->howto = &arm64_howto_table[14]; + return TRUE; + } + break; + case BFD_MACH_O_ARM64_RELOC_POINTER_TO_GOT: + if (reloc.r_length == 2 && reloc.r_pcrel == 1) + { + res->howto = &arm64_howto_table[15]; + return TRUE; + } + break; + default: + break; + } + return FALSE; +} + +static reloc_howto_type * +bfd_mach_o_arm64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, + bfd_reloc_code_real_type code) +{ + unsigned int i; + + for (i = 0; + i < sizeof (arm64_howto_table) / sizeof (*arm64_howto_table); + i++) + if (code == arm64_howto_table[i].type) + return &arm64_howto_table[i]; + return NULL; +} + +static reloc_howto_type * +bfd_mach_o_arm64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *name ATTRIBUTE_UNUSED) +{ + return NULL; +} + +#define TARGET_NAME aarch64_mach_o_vec +#define TARGET_STRING "mach-o-arm64" +#define TARGET_ARCHITECTURE bfd_arch_aarch64 +#define TARGET_PAGESIZE 4096 +#define TARGET_BIG_ENDIAN 0 +#define TARGET_ARCHIVE 0 +#define TARGET_PRIORITY 0 +#include "mach-o-target.c" + +#undef TARGET_NAME +#undef TARGET_STRING +#undef TARGET_ARCHIVE +#undef TARGET_PRIORITY diff --git a/bfd/mach-o-arm.c b/bfd/mach-o-arm.c new file mode 100644 index 0000000..b7c14df --- /dev/null +++ b/bfd/mach-o-arm.c @@ -0,0 +1,326 @@ +/* ARM Mach-O support for BFD. + Copyright (C) 2015 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" +#include "mach-o/arm.h" + +#define bfd_mach_o_object_p bfd_mach_o_arm_object_p +#define bfd_mach_o_core_p bfd_mach_o_arm_core_p +#define bfd_mach_o_mkobject bfd_mach_o_arm_mkobject + +#define bfd_mach_o_canonicalize_one_reloc bfd_mach_o_arm_canonicalize_one_reloc +#define bfd_mach_o_swap_reloc_out NULL +#define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_arm_bfd_reloc_type_lookup +#define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_arm_bfd_reloc_name_lookup + +#define bfd_mach_o_print_thread NULL +#define bfd_mach_o_tgt_seg_table NULL +#define bfd_mach_o_section_type_valid_for_tgt NULL + +static const bfd_target * +bfd_mach_o_arm_object_p (bfd *abfd) +{ + return bfd_mach_o_header_p (abfd, 0, 0, BFD_MACH_O_CPU_TYPE_ARM); +} + +static const bfd_target * +bfd_mach_o_arm_core_p (bfd *abfd) +{ + return bfd_mach_o_header_p (abfd, 0, + BFD_MACH_O_MH_CORE, BFD_MACH_O_CPU_TYPE_ARM); +} + +static bfd_boolean +bfd_mach_o_arm_mkobject (bfd *abfd) +{ + bfd_mach_o_data_struct *mdata; + + if (!bfd_mach_o_mkobject_init (abfd)) + return FALSE; + + mdata = bfd_mach_o_get_data (abfd); + mdata->header.magic = BFD_MACH_O_MH_MAGIC; + mdata->header.cputype = BFD_MACH_O_CPU_TYPE_ARM; + mdata->header.cpusubtype = BFD_MACH_O_CPU_SUBTYPE_ARM_ALL; + mdata->header.byteorder = BFD_ENDIAN_LITTLE; + mdata->header.version = 1; + + return TRUE; +} + +static reloc_howto_type arm_howto_table[]= +{ + /* 0 */ + HOWTO (BFD_RELOC_32, 0, 2, 32, FALSE, 0, + complain_overflow_bitfield, + NULL, "32", + FALSE, 0xffffffff, 0xffffffff, FALSE), + HOWTO (BFD_RELOC_16, 0, 1, 16, FALSE, 0, + complain_overflow_bitfield, + NULL, "16", + FALSE, 0xffff, 0xffff, FALSE), + HOWTO (BFD_RELOC_8, 0, 0, 8, FALSE, 0, + complain_overflow_bitfield, + NULL, "8", + FALSE, 0xff, 0xff, FALSE), + HOWTO (BFD_RELOC_32_PCREL, 0, 2, 32, TRUE, 0, + complain_overflow_bitfield, + NULL, "DISP32", + FALSE, 0xffffffff, 0xffffffff, TRUE), + /* 4 */ + HOWTO (BFD_RELOC_16_PCREL, 0, 1, 16, TRUE, 0, + complain_overflow_bitfield, + NULL, "DISP16", + FALSE, 0xffff, 0xffff, TRUE), + HOWTO (BFD_RELOC_MACH_O_SECTDIFF, 0, 2, 32, FALSE, 0, + complain_overflow_bitfield, + NULL, "SECTDIFF_32", + FALSE, 0xffffffff, 0xffffffff, FALSE), + HOWTO (BFD_RELOC_MACH_O_LOCAL_SECTDIFF, 0, 2, 32, FALSE, 0, + complain_overflow_bitfield, + NULL, "LSECTDIFF_32", + FALSE, 0xffffffff, 0xffffffff, FALSE), + HOWTO (BFD_RELOC_MACH_O_PAIR, 0, 2, 32, FALSE, 0, + complain_overflow_bitfield, + NULL, "PAIR_32", + FALSE, 0xffffffff, 0xffffffff, FALSE), + /* 8 */ + HOWTO (BFD_RELOC_MACH_O_SECTDIFF, 0, 1, 16, FALSE, 0, + complain_overflow_bitfield, + NULL, "SECTDIFF_16", + FALSE, 0xffff, 0xffff, FALSE), + HOWTO (BFD_RELOC_MACH_O_LOCAL_SECTDIFF, 0, 1, 16, FALSE, 0, + complain_overflow_bitfield, + NULL, "LSECTDIFF_16", + FALSE, 0xffff, 0xffff, FALSE), + HOWTO (BFD_RELOC_MACH_O_PAIR, 0, 1, 16, FALSE, 0, + complain_overflow_bitfield, + NULL, "PAIR_16", + FALSE, 0xffff, 0xffff, FALSE), + HOWTO (BFD_RELOC_ARM_PCREL_CALL, 2, 2, 24, TRUE, 0, + complain_overflow_signed, + NULL, "BR24", + FALSE, 0x00ffffff, 0x00ffffff, TRUE), + /* 12 */ + HOWTO (BFD_RELOC_ARM_MOVW, 0, 2, 16, FALSE, 0, + complain_overflow_dont, + NULL, "MOVW", + FALSE, 0x000f0fff, 0x000f0fff, FALSE), + HOWTO (BFD_RELOC_MACH_O_PAIR, 0, 2, 16, FALSE, 0, + complain_overflow_bitfield, + NULL, "PAIR_W", + FALSE, 0x000f0fff, 0x000f0fff, FALSE), + HOWTO (BFD_RELOC_ARM_MOVT, 0, 2, 16, FALSE, 0, + complain_overflow_bitfield, + NULL, "MOVT", + FALSE, 0x000f0fff, 0x000f0fff, FALSE), + HOWTO (BFD_RELOC_MACH_O_PAIR, 0, 2, 16, FALSE, 0, + complain_overflow_bitfield, + NULL, "PAIR_T", + FALSE, 0x000f0fff, 0x000f0fff, FALSE), + /* 16 */ + HOWTO (BFD_RELOC_THUMB_PCREL_BLX, 2, 2, 24, TRUE, 0, + complain_overflow_signed, + NULL, "TBR22", + FALSE, 0x07ff2fff, 0x07ff2fff, TRUE) +}; + +static bfd_boolean +bfd_mach_o_arm_canonicalize_one_reloc (bfd *abfd, + struct mach_o_reloc_info_external *raw, + arelent *res, asymbol **syms) + { + bfd_mach_o_reloc_info reloc; + + if (!bfd_mach_o_pre_canonicalize_one_reloc (abfd, raw, &reloc, res, syms)) + return FALSE; + + if (reloc.r_scattered) + { + switch (reloc.r_type) + { + case BFD_MACH_O_ARM_RELOC_PAIR: + if (reloc.r_length == 2) + { + res->howto = &arm_howto_table[7]; + res->address = res[-1].address; + return TRUE; + } + else if (reloc.r_length == 1) + { + res->howto = &arm_howto_table[10]; + res->address = res[-1].address; + return TRUE; + } + return FALSE; + case BFD_MACH_O_ARM_RELOC_SECTDIFF: + if (reloc.r_length == 2) + { + res->howto = &arm_howto_table[5]; + return TRUE; + } + else if (reloc.r_length == 1) + { + res->howto = &arm_howto_table[8]; + return TRUE; + } + return FALSE; + case BFD_MACH_O_ARM_RELOC_LOCAL_SECTDIFF: + if (reloc.r_length == 2) + { + res->howto = &arm_howto_table[6]; + return TRUE; + } + else if (reloc.r_length == 1) + { + res->howto = &arm_howto_table[9]; + return TRUE; + } + return FALSE; + case BFD_MACH_O_ARM_RELOC_HALF_SECTDIFF: + switch (reloc.r_length) + { + case 2: /* :lower16: for movw arm. */ + res->howto = &arm_howto_table[12]; + return TRUE; + case 3: /* :upper16: for movt arm. */ + res->howto = &arm_howto_table[14]; + return TRUE; + } + return FALSE; + default: + return FALSE; + } + } + else + { + switch (reloc.r_type) + { + case BFD_MACH_O_ARM_RELOC_VANILLA: + switch ((reloc.r_length << 1) | reloc.r_pcrel) + { + case 0: /* len = 0, pcrel = 0 */ + res->howto = &arm_howto_table[2]; + return TRUE; + case 2: /* len = 1, pcrel = 0 */ + res->howto = &arm_howto_table[1]; + return TRUE; + case 3: /* len = 1, pcrel = 1 */ + res->howto = &arm_howto_table[4]; + return TRUE; + case 4: /* len = 2, pcrel = 0 */ + res->howto = &arm_howto_table[0]; + return TRUE; + case 5: /* len = 2, pcrel = 1 */ + res->howto = &arm_howto_table[3]; + return TRUE; + default: + return FALSE; + } + break; + case BFD_MACH_O_ARM_RELOC_BR24: + if (reloc.r_length == 2 && reloc.r_pcrel == 1) + { + res->howto = &arm_howto_table[11]; + return TRUE; + } + else + return FALSE; + break; + case BFD_MACH_O_THUMB_RELOC_BR22: + if (reloc.r_length == 2 && reloc.r_pcrel == 1) + { + res->howto = &arm_howto_table[16]; + return TRUE; + } + else + return FALSE; + break; + case BFD_MACH_O_ARM_RELOC_HALF: + if (reloc.r_pcrel == 0) + switch (reloc.r_length) + { + case 0: /* :lower16: for movw arm. */ + res->howto = &arm_howto_table[12]; + return TRUE; + case 1: /* :upper16: for movt arm. */ + res->howto = &arm_howto_table[14]; + return TRUE; + } + return FALSE; + case BFD_MACH_O_ARM_RELOC_PAIR: + if (res[-1].howto == &arm_howto_table[12] + && reloc.r_length == 0) + { + /* Pair for :lower16: of movw arm. */ + res->howto = &arm_howto_table[13]; + /* This reloc contains the other half in its r_address field. */ + res[-1].addend += (res->address & 0xffff) << 16; + res->address = res[-1].address; + return TRUE; + } + else if (res[-1].howto == &arm_howto_table[14] + && reloc.r_length == 1) + { + /* Pair for :upper16: of movt arm. */ + res->howto = &arm_howto_table[15]; + /* This reloc contains the other half in its r_address field. */ + res[-1].addend += res->address & 0xffff; + res->address = res[-1].address; + return TRUE; + } + return FALSE; + default: + return FALSE; + } + } +} + +static reloc_howto_type * +bfd_mach_o_arm_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, + bfd_reloc_code_real_type code) +{ + unsigned int i; + + for (i = 0; i < sizeof (arm_howto_table) / sizeof (*arm_howto_table); i++) + if (code == arm_howto_table[i].type) + return &arm_howto_table[i]; + return NULL; +} + +static reloc_howto_type * +bfd_mach_o_arm_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *name ATTRIBUTE_UNUSED) +{ + return NULL; +} + +#define TARGET_NAME arm_mach_o_vec +#define TARGET_STRING "mach-o-arm" +#define TARGET_ARCHITECTURE bfd_arch_arm +#define TARGET_PAGESIZE 4096 +#define TARGET_BIG_ENDIAN 0 +#define TARGET_ARCHIVE 0 +#define TARGET_PRIORITY 0 +#include "mach-o-target.c" diff --git a/bfd/mach-o-x86-64.c b/bfd/mach-o-x86-64.c index 5914ae8..05046d7 100644 --- a/bfd/mach-o-x86-64.c +++ b/bfd/mach-o-x86-64.c @@ -266,12 +266,12 @@ bfd_mach_o_x86_64_swap_reloc_out (arelent *rel, bfd_mach_o_reloc_info *rinfo) rinfo->r_pcrel = 1; rinfo->r_length = 2; break; - case BFD_RELOC_MACH_O_X86_64_SUBTRACTOR32: + case BFD_RELOC_MACH_O_SUBTRACTOR32: rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SUBTRACTOR; rinfo->r_pcrel = 0; rinfo->r_length = 2; break; - case BFD_RELOC_MACH_O_X86_64_SUBTRACTOR64: + case BFD_RELOC_MACH_O_SUBTRACTOR64: rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SUBTRACTOR; rinfo->r_pcrel = 0; rinfo->r_length = 3; diff --git a/bfd/reloc.c b/bfd/reloc.c index bbc376e..17c470e 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -6590,6 +6590,14 @@ ENUM BFD_RELOC_MACH_O_PAIR ENUMDOC Pair of relocation. Contains the first symbol. +ENUM + BFD_RELOC_MACH_O_SUBTRACTOR32 +ENUMDOC + Symbol will be substracted. Must be followed by a BFD_RELOC_32. +ENUM + BFD_RELOC_MACH_O_SUBTRACTOR64 +ENUMDOC + Symbol will be substracted. Must be followed by a BFD_RELOC_64. ENUM BFD_RELOC_MACH_O_X86_64_BRANCH32 @@ -6608,14 +6616,6 @@ ENUMDOC Used when loading a GOT entry with movq. It is specially marked so that the linker could optimize the movq to a leaq if possible. ENUM - BFD_RELOC_MACH_O_X86_64_SUBTRACTOR32 -ENUMDOC - Symbol will be substracted. Must be followed by a BFD_RELOC_64. -ENUM - BFD_RELOC_MACH_O_X86_64_SUBTRACTOR64 -ENUMDOC - Symbol will be substracted. Must be followed by a BFD_RELOC_64. -ENUM BFD_RELOC_MACH_O_X86_64_PCREL32_1 ENUMDOC Same as BFD_RELOC_32_PCREL but with an implicit -1 addend. @@ -6628,6 +6628,24 @@ ENUM ENUMDOC Same as BFD_RELOC_32_PCREL but with an implicit -4 addend. + +ENUM + BFD_RELOC_MACH_O_ARM64_ADDEND +ENUMDOC + Addend for PAGE or PAGEOFF. +ENUM + BFD_RELOC_MACH_O_ARM64_GOT_LOAD_PAGE21 +ENUMDOC + Relative offset to page of GOT slot. +ENUM + BFD_RELOC_MACH_O_ARM64_GOT_LOAD_PAGEOFF12 +ENUMDOC + Relative offset within page of GOT slot. +ENUM + BFD_RELOC_MACH_O_ARM64_POINTER_TO_GOT +ENUMDOC + Address of a GOT entry. + ENUM BFD_RELOC_MICROBLAZE_32_LO ENUMDOC diff --git a/bfd/targets.c b/bfd/targets.c index 51f2198..bfb34f1 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -571,6 +571,7 @@ extern const bfd_target aarch64_elf64_be_vec; extern const bfd_target aarch64_elf64_be_cloudabi_vec; extern const bfd_target aarch64_elf64_le_vec; extern const bfd_target aarch64_elf64_le_cloudabi_vec; +extern const bfd_target aarch64_mach_o_vec; extern const bfd_target alpha_ecoff_le_vec; extern const bfd_target alpha_elf64_vec; extern const bfd_target alpha_elf64_fbsd_vec; @@ -598,6 +599,7 @@ extern const bfd_target arm_elf32_symbian_be_vec; extern const bfd_target arm_elf32_symbian_le_vec; extern const bfd_target arm_elf32_vxworks_be_vec; extern const bfd_target arm_elf32_vxworks_le_vec; +extern const bfd_target arm_mach_o_vec; extern const bfd_target arm_pe_be_vec; extern const bfd_target arm_pe_le_vec; extern const bfd_target arm_pe_epoc_be_vec; @@ -953,6 +955,7 @@ static const bfd_target * const _bfd_target_vector[] = &aarch64_elf64_be_cloudabi_vec, &aarch64_elf64_le_vec, &aarch64_elf64_le_cloudabi_vec, + &aarch64_mach_o_vec, #endif #ifdef BFD64 @@ -998,6 +1001,7 @@ static const bfd_target * const _bfd_target_vector[] = &arm_elf32_symbian_le_vec, &arm_elf32_vxworks_be_vec, &arm_elf32_vxworks_le_vec, + &arm_mach_o_vec, &arm_pe_be_vec, &arm_pe_le_vec, &arm_pe_epoc_be_vec, |