[Patch 2/2] Add Mach-O x86-64 target vector

Tristan Gingold gingold@adacore.com
Mon Jan 11 16:17:00 GMT 2010


Hi,

this patch adds support for x86-64 architecture to Mach-O.  It currently mostly deals with reading
relocations.

Ok to commit ?

Tristan.

2010-01-08  Tristan Gingold  <gingold@adacore.com>

	* config.bfd: Remove duplicated target vector for i386-*-darwin.
	Appends new arch instead of overriding.
	Use mach_o_x86_64_vec for x86_64-*-darwin.
	* configure.in: Add mach_o_x86_64_vec.
	* configure: Regenerate.
	* targets.c: Declare mach_o_x86_64_vec, add it to _bfd_target_vector.
	* Makefile.am (BFD64_BACKENDS): Add mach-o-x86-64.lo
	(BFD64_BACKENDS_CFILES): Add mach-o-x86-64.c
	* Makefile.in: Regenerate.
	* mach-o-x86-64.c: New file.
---
 bfd/Makefile.am     |    2 +
 bfd/config.bfd      |   10 +-
 bfd/configure.in    |    1 +
 bfd/mach-o-x86-64.c |  280 +++++++++++++++++++++++++++++++++++++++++++++++++++
 bfd/targets.c       |    4 +
 5 files changed, 292 insertions(+), 5 deletions(-)
 create mode 100644 bfd/mach-o-x86-64.c

diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index b569f84..03aa24b 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -609,6 +609,7 @@ BFD64_BACKENDS = \
 	elf64-x86-64.lo \
 	elf64.lo \
 	elfn32-mips.lo \
+	mach-o-x86-64.lo \
 	mmo.lo \
 	nlm32-alpha.lo \
 	nlm64.lo \
@@ -639,6 +640,7 @@ BFD64_BACKENDS_CFILES = \
 	elf64-x86-64.c \
 	elf64.c \
 	elfn32-mips.c \
+	mach-o-x86-64.c \
 	mmo.c \
 	nlm32-alpha.c \
 	nlm64.c \
diff --git a/bfd/config.bfd b/bfd/config.bfd
index c331a97..9290b83 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -543,8 +543,8 @@ case "${targ}" in
     ;;
   i[3-7]86-*-darwin* | i[3-7]86-*-macos10* | i[3-7]86-*-rhapsody*)
     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"
+    targ_selvecs="mach_o_le_vec mach_o_be_vec mach_o_fat_vec pef_vec pef_xlib_vec sym_vec"
+    targ_archs="$targ_archs bfd_powerpc_arch bfd_rs6000_arch"
     ;;
  i[3-7]86-sequent-bsd*)
     targ_defvec=i386dynix_vec
@@ -605,9 +605,9 @@ case "${targ}" in
     ;;
 #ifdef BFD64
   x86_64-*-darwin*)
-    targ_defvec=mach_o_le_vec
+    targ_defvec=mach_o_x86_64_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"
+    targ_archs="$targ_archs bfd_powerpc_arch bfd_rs6000_arch"
     want64=true
     ;;
   x86_64-*-dicos*)
@@ -1153,7 +1153,7 @@ case "${targ}" in
   powerpc-*-darwin* | powerpc-*-macos10* | powerpc-*-rhapsody*)
     targ_defvec=mach_o_be_vec
     targ_selvecs="mach_o_be_vec mach_o_le_vec mach_o_fat_vec pef_vec pef_xlib_vec sym_vec"
-    targ_archs="bfd_powerpc_arch bfd_rs6000_arch bfd_i386_arch"
+    targ_archs="$targ_archs bfd_i386_arch"
     ;;
   powerpc-*-macos*)
     targ_defvec=pmac_xcoff_vec
diff --git a/bfd/configure.in b/bfd/configure.in
index 3713d56..b246afc 100644
--- a/bfd/configure.in
+++ b/bfd/configure.in
@@ -857,6 +857,7 @@ do
     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" ;;
+    mach_o_x86_64_vec)          tb="$tb mach-o-x86-64.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-x86-64.c b/bfd/mach-o-x86-64.c
new file mode 100644
index 0000000..005315d
--- /dev/null
+++ b/bfd/mach-o-x86-64.c
@@ -0,0 +1,280 @@
+/* Intel x86-64 Mach-O support for BFD.
+   Copyright 2010
+   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_x86_64_object_p
+#define bfd_mach_o_core_p bfd_mach_o_x86_64_core_p
+#define bfd_mach_o_mkobject bfd_mach_o_x86_64_mkobject
+
+static const bfd_target *
+bfd_mach_o_x86_64_object_p (bfd *abfd)
+{
+  return bfd_mach_o_header_p (abfd, 0, BFD_MACH_O_CPU_TYPE_X86_64);
+}
+
+static const bfd_target *
+bfd_mach_o_x86_64_core_p (bfd *abfd)
+{
+  return bfd_mach_o_header_p (abfd,
+                              BFD_MACH_O_MH_CORE, BFD_MACH_O_CPU_TYPE_X86_64);
+}
+
+static bfd_boolean
+bfd_mach_o_x86_64_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_X86_64;
+  mdata->header.cpusubtype = BFD_MACH_O_CPU_SUBTYPE_X86_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 x86_64_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_32_PCREL, 0, 2, 32, TRUE, 0,
+	complain_overflow_bitfield,
+	NULL, "DISP32",
+	FALSE, 0xffffffff, 0xffffffff, TRUE),
+  HOWTO(BFD_RELOC_MACH_O_X86_64_PCREL32_1, 0, 2, 32, TRUE, 0,
+	complain_overflow_bitfield,
+	NULL, "DISP32_1",
+	FALSE, 0xffffffff, 0xffffffff, TRUE),
+  /* 4 */
+  HOWTO(BFD_RELOC_MACH_O_X86_64_PCREL32_2, 0, 2, 32, TRUE, 0,
+	complain_overflow_bitfield,
+	NULL, "DISP32_2",
+	FALSE, 0xffffffff, 0xffffffff, TRUE),
+  HOWTO(BFD_RELOC_MACH_O_X86_64_PCREL32_4, 0, 2, 32, TRUE, 0,
+	complain_overflow_bitfield,
+	NULL, "DISP32_4",
+	FALSE, 0xffffffff, 0xffffffff, TRUE),
+  HOWTO(BFD_RELOC_MACH_O_X86_64_BRANCH32, 0, 2, 32, TRUE, 0,
+	complain_overflow_bitfield,
+	NULL, "BRANCH32",
+	FALSE, 0xffffffff, 0xffffffff, TRUE),
+  HOWTO(BFD_RELOC_MACH_O_X86_64_GOT_LOAD, 0, 2, 32, TRUE, 0,
+	complain_overflow_bitfield,
+	NULL, "GOT_LOAD",
+	FALSE, 0xffffffff, 0xffffffff, TRUE),
+  /* 8 */
+  HOWTO(BFD_RELOC_MACH_O_X86_64_SUBTRACTOR32, 0, 2, 32, FALSE, 0,
+	complain_overflow_bitfield,
+	NULL, "SUBTRACTOR32",
+	FALSE, 0xffffffff, 0xffffffff, FALSE),
+  HOWTO(BFD_RELOC_MACH_O_X86_64_SUBTRACTOR64, 0, 4, 64, FALSE, 0,
+	complain_overflow_bitfield,
+	NULL, "SUBTRACTOR64",
+	FALSE, MINUS_ONE, MINUS_ONE, FALSE),
+  HOWTO(BFD_RELOC_MACH_O_X86_64_GOT, 0, 2, 32, TRUE, 0,
+	complain_overflow_bitfield,
+	NULL, "GOT",
+	FALSE, 0xffffffff, 0xffffffff, TRUE),
+  HOWTO(BFD_RELOC_MACH_O_X86_64_BRANCH8, 0, 0, 8, TRUE, 0,
+	complain_overflow_bitfield,
+	NULL, "BRANCH8",
+	FALSE, 0xff, 0xff, TRUE),
+};
+
+static bfd_boolean
+bfd_mach_o_x86_64_swap_reloc_in (arelent *res, bfd_mach_o_reloc_info *reloc)
+{
+  /* On x86-64, scattered relocs are not used.  */
+  if (reloc->r_scattered)
+    return FALSE;
+
+  switch (reloc->r_type)
+    {
+    case BFD_MACH_O_X86_64_RELOC_UNSIGNED:
+      if (reloc->r_pcrel)
+        return FALSE;
+      switch (reloc->r_length)
+        {
+        case 2:
+          res->howto = &x86_64_howto_table[1];
+          return TRUE;
+        case 3:
+          res->howto = &x86_64_howto_table[0];
+          return TRUE;
+        default:
+          return FALSE;
+        }
+    case BFD_MACH_O_X86_64_RELOC_SIGNED:
+      if (reloc->r_length == 2 && reloc->r_pcrel)
+        {
+          res->howto = &x86_64_howto_table[2];
+          return TRUE;
+        }
+      break;
+    case BFD_MACH_O_X86_64_RELOC_BRANCH:
+      if (!reloc->r_pcrel)
+        return FALSE;
+      switch (reloc->r_length)
+        {
+        case 2:
+          res->howto = &x86_64_howto_table[6];
+          return TRUE;
+        default:
+          return FALSE;
+        }
+      break;
+    case BFD_MACH_O_X86_64_RELOC_GOT_LOAD:
+      if (reloc->r_length == 2 && reloc->r_pcrel && reloc->r_extern)
+        {
+          res->howto = &x86_64_howto_table[7];
+          return TRUE;
+        }
+      break;
+    case BFD_MACH_O_X86_64_RELOC_GOT:
+      if (reloc->r_length == 2 && reloc->r_pcrel && reloc->r_extern)
+        {
+          res->howto = &x86_64_howto_table[10];
+          return TRUE;
+        }
+      break;
+    case BFD_MACH_O_X86_64_RELOC_SUBTRACTOR:
+      if (reloc->r_pcrel)
+        return FALSE;
+      switch (reloc->r_length)
+        {
+        case 2:
+          res->howto = &x86_64_howto_table[8];
+          return TRUE;
+        case 3:
+          res->howto = &x86_64_howto_table[9];
+          return TRUE;
+        default:
+          return FALSE;
+        }
+      break;
+    case BFD_MACH_O_X86_64_RELOC_SIGNED_1:
+      if (reloc->r_length == 2 && reloc->r_pcrel)
+        {
+          res->howto = &x86_64_howto_table[3];
+          return TRUE;
+        }
+      break;
+    case BFD_MACH_O_X86_64_RELOC_SIGNED_2:
+      if (reloc->r_length == 2 && reloc->r_pcrel)
+        {
+          res->howto = &x86_64_howto_table[4];
+          return TRUE;
+        }
+      break;
+    case BFD_MACH_O_X86_64_RELOC_SIGNED_4:
+      if (reloc->r_length == 2 && reloc->r_pcrel)
+        {
+          res->howto = &x86_64_howto_table[5];
+          return TRUE;
+        }
+      break;
+    default:
+      return FALSE;
+    }
+  return FALSE;
+}
+
+static bfd_boolean
+bfd_mach_o_x86_64_swap_reloc_out (arelent *rel, bfd_mach_o_reloc_info *rinfo)
+{
+  rinfo->r_address = rel->address;
+  switch (rel->howto->type)
+    {
+    case BFD_RELOC_64:
+      rinfo->r_scattered = 0;
+      rinfo->r_type = BFD_MACH_O_X86_64_RELOC_UNSIGNED;
+      rinfo->r_pcrel = 0;
+      rinfo->r_length = rel->howto->size; /* Correct in practice.  */
+      if ((*rel->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
+        {
+          rinfo->r_extern = 0;
+          rinfo->r_value = (*rel->sym_ptr_ptr)->section->target_index;
+        }
+      else
+        {
+          rinfo->r_extern = 1;
+          rinfo->r_value = (*rel->sym_ptr_ptr)->udata.i;
+        }
+      break;
+    default:
+      return FALSE;
+    }
+  return TRUE;
+}
+
+static reloc_howto_type *
+bfd_mach_o_x86_64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                                         bfd_reloc_code_real_type code)
+{
+  unsigned int i;
+
+  for (i = 0;
+       i < sizeof (x86_64_howto_table) / sizeof (*x86_64_howto_table);
+       i++)
+    if (code == x86_64_howto_table[i].type)
+      return &x86_64_howto_table[i];
+  return NULL;
+}
+
+static reloc_howto_type *
+bfd_mach_o_x86_64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                                         const char *name ATTRIBUTE_UNUSED)
+{
+  return NULL;
+}
+
+#define bfd_mach_o_swap_reloc_in bfd_mach_o_x86_64_swap_reloc_in
+#define bfd_mach_o_swap_reloc_out bfd_mach_o_x86_64_swap_reloc_out
+
+#define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_x86_64_bfd_reloc_type_lookup
+#define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_x86_64_bfd_reloc_name_lookup
+#define bfd_mach_o_print_thread NULL
+
+#define TARGET_NAME 		mach_o_x86_64_vec
+#define TARGET_STRING 		"mach-o-x86-64"
+#define TARGET_ARCHITECTURE	bfd_arch_i386
+#define TARGET_BIG_ENDIAN 	0
+#define TARGET_ARCHIVE 		0
+#include "mach-o-target.c"
diff --git a/bfd/targets.c b/bfd/targets.c
index d9811a8..ad22a29 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -760,6 +760,7 @@ 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 mach_o_x86_64_vec;
 extern const bfd_target maxqcoff_vec;
 extern const bfd_target mcore_pe_big_vec;
 extern const bfd_target mcore_pe_little_vec;
@@ -1134,6 +1135,9 @@ static const bfd_target * const _bfd_target_vector[] =
 	&mach_o_le_vec,
 	&mach_o_fat_vec,
 	&mach_o_i386_vec,
+#ifdef BFD64
+	&mach_o_x86_64_vec,
+#endif
 	&maxqcoff_vec,
 	&mcore_pe_big_vec,
 	&mcore_pe_little_vec,
-- 
1.6.2



More information about the Binutils mailing list