This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Add plugin support for bfd


The attached patch adds support for plugins in bfd. It does so by
creating a plugin target. It is not a full target, but is enough to
add plugin support for nm and ar. The plugin interface is the same
interface used by gold. It just passes fewer callbacks to onload.

This is needed for getting build systems that use archives to works
with LLVM's LTO. The problem that exists currently is that when given
LLVM IL files, ar will not create a symbol table for the archive and
gold will refuse to use it.

This should also be useful for GCC's LTO branch. That branch uses fat
elf files with both IL and regular code. With this patch it should be
possible to do

nm foo.o (prints the ELF symbol table)
nm --plugin plugin.so foo.o (prints the IL symbol table)

some bugs we (LTO developers) had in the past were caused by
inconsistencies between the tables, so this would be a nice debugging
tool. We just have to make sure that the plugin target is tried first
(not included in this patch).

To enable plugin support, just build with --enable-plugins (the same
option used for gold).

I would like any comments you might have, but there are some items I
don't like too much about the patch and I would really appreciate if
you have suggestions on how to improve it:

1) I use a environment variable in bfd to find the plugin.
2) The --plugin option is implemented using the environment variable.
3) The check for --enable-plugin is duplicated in many configure.in

In contrast with this, gold uses only a command line option. This is
very nice, but gold has the advantage that it is always called from
GCC. GCC (in the LTO branch) knows where to find its plugin and passes
the correct option to gold. That is not true for other utilities (nm
and ar). Also, in most build systems there is no NMFLAGS or ARFLAGS,
so they have to search for the plugin. One option that is more
complicated than the environment variable but maybe better is to do
what gcc does: Take -B options and search for plugins there. Also have
reasonable compile time defaults so that normal users don't have to
add -B to the command line.

Cheers,
Rafael
diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index 8d67cb8..e3f90d2 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -25,7 +25,7 @@ bfdlib_LTLIBRARIES = libbfd.la
 
 WARN_CFLAGS = @WARN_CFLAGS@
 NO_WERROR = @NO_WERROR@
-AM_CFLAGS = $(WARN_CFLAGS)
+AM_CFLAGS = $(WARN_CFLAGS) $(LFS_CFLAGS)
 
 # bfd.h goes here, for now
 BFD_H = bfd.h
@@ -356,6 +356,7 @@ BFD32_BACKENDS = \
 	pe-mips.lo \
 	pei-mips.lo \
 	peigen.lo \
+	plugin.lo \
 	ppcboot.lo \
 	reloc16.lo \
 	riscix.lo \
@@ -538,6 +539,7 @@ BFD32_BACKENDS_CFILES = \
 	pei-sh.c \
 	pe-mips.c \
 	pei-mips.c \
+	plugin.c \
 	ppcboot.c \
 	reloc16.c \
 	riscix.c \
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 994759d..ee98d18 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -4829,6 +4829,7 @@ struct bfd
       struct netbsd_core_struct *netbsd_core_data;
       struct mach_o_data_struct *mach_o_data;
       struct mach_o_fat_data_struct *mach_o_fat_data;
+      struct plugin_data_struct *plugin_data;
       struct bfd_pef_data_struct *pef_data;
       struct bfd_pef_xlib_data_struct *pef_xlib_data;
       struct bfd_sym_data_struct *sym_data;
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 847da52..ad724ba 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -235,6 +235,7 @@ CODE_FRAGMENT
 .      struct netbsd_core_struct *netbsd_core_data;
 .      struct mach_o_data_struct *mach_o_data;
 .      struct mach_o_fat_data_struct *mach_o_fat_data;
+.      struct plugin_data_struct *plugin_data;
 .      struct bfd_pef_data_struct *pef_data;
 .      struct bfd_pef_xlib_data_struct *pef_xlib_data;
 .      struct bfd_sym_data_struct *sym_data;
diff --git a/bfd/config.bfd b/bfd/config.bfd
index d9865e6..45f762e 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -137,6 +137,12 @@ case "${targ}" in
     exit 1
     ;;
 
+  plugin)
+    targ_defvec=plugin_vec
+    targ_selvecs="plugin_vec"
+    targ_archs="bfd_i386_arch"
+    ;;
+
 # START OF targmatch.h
 #ifdef BFD64
   alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu)
diff --git a/bfd/configure.in b/bfd/configure.in
index a444418..45c76c9 100644
--- a/bfd/configure.in
+++ b/bfd/configure.in
@@ -137,6 +137,12 @@ AM_PO_SUBDIRS
 . ${srcdir}/configure.host
 
 AC_SUBST(HDEFINES)
+
+dnl Force support for large files by default.  This may need to be
+dnl host dependent.  If build == host, we can check getconf LFS_CFLAGS.
+LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
+AC_SUBST(LFS_CFLAGS)
+
 AC_PROG_INSTALL
 
 BFD_HOST_64BIT_LONG=0
@@ -522,6 +528,19 @@ AC_SUBST(SHARED_LIBADD)
 
 # target stuff:
 
+AC_ARG_ENABLE([plugins],
+[  --enable-plugins        linker plugins],
+[case "${enableval}" in
+  yes | "") plugins=yes ;;
+  no) plugins=no ;;
+  *) plugins=yes ;;
+ esac],
+[plugins=no])
+
+if test "$plugins" = "yes"; then
+  enable_targets="$enable_targets plugin";
+fi
+
 # Canonicalize the secondary target names.
 if test -n "$enable_targets" ; then
     for targ in `echo $enable_targets | sed 's/,/ /g'`
@@ -854,6 +873,7 @@ do
     pef_vec)                    tb="$tb pef.lo" ;;
     pef_xlib_vec)               tb="$tb pef.lo" ;;
     pdp11_aout_vec)		tb="$tb pdp11.lo" ;;
+    plugin_vec)                 tb="$tb plugin.lo" ;;
     pmac_xcoff_vec)		tb="$tb coff-rs6000.lo xcofflink.lo" ;;
     ppcboot_vec)		tb="$tb ppcboot.lo" ;;
     riscix_vec)			tb="$tb aout32.lo riscix.lo" ;;
diff --git a/bfd/plugin.c b/bfd/plugin.c
new file mode 100644
index 0000000..28b0e58
--- /dev/null
+++ b/bfd/plugin.c
@@ -0,0 +1,434 @@
+/* Plugin support for BFD.
+   Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2008
+   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 <assert.h>
+#include <dlfcn.h>
+#include <stdarg.h>
+#include "plugin-api.h"
+#include "sysdep.h"
+#include "plugin.h"
+#include "libbfd.h"
+
+#define bfd_plugin_close_and_cleanup                  _bfd_generic_close_and_cleanup
+#define bfd_plugin_bfd_free_cached_info               _bfd_generic_bfd_free_cached_info
+#define bfd_plugin_new_section_hook                   _bfd_generic_new_section_hook
+#define bfd_plugin_get_section_contents               _bfd_generic_get_section_contents
+#define bfd_plugin_get_section_contents_in_window     _bfd_generic_get_section_contents_in_window
+#define bfd_plugin_bfd_copy_private_header_data       _bfd_generic_bfd_copy_private_header_data
+#define bfd_plugin_bfd_merge_private_bfd_data         _bfd_generic_bfd_merge_private_bfd_data
+#define bfd_plugin_bfd_copy_private_header_data       _bfd_generic_bfd_copy_private_header_data
+#define bfd_plugin_bfd_set_private_flags              _bfd_generic_bfd_set_private_flags
+#define bfd_plugin_core_file_matches_executable_p     generic_core_file_matches_executable_p
+#define bfd_plugin_bfd_is_local_label_name            _bfd_nosymbols_bfd_is_local_label_name
+#define bfd_plugin_bfd_is_target_special_symbol       ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
+#define bfd_plugin_get_lineno                         _bfd_nosymbols_get_lineno
+#define bfd_plugin_find_nearest_line                  _bfd_nosymbols_find_nearest_line
+#define bfd_plugin_find_inliner_info                  _bfd_nosymbols_find_inliner_info
+#define bfd_plugin_bfd_make_debug_symbol              _bfd_nosymbols_bfd_make_debug_symbol
+#define bfd_plugin_read_minisymbols                   _bfd_generic_read_minisymbols
+#define bfd_plugin_minisymbol_to_symbol               _bfd_generic_minisymbol_to_symbol
+#define bfd_plugin_set_arch_mach                      bfd_default_set_arch_mach
+#define bfd_plugin_set_section_contents               _bfd_generic_set_section_contents
+#define bfd_plugin_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
+#define bfd_plugin_bfd_relax_section                  bfd_generic_relax_section
+#define bfd_plugin_bfd_link_hash_table_create         _bfd_generic_link_hash_table_create
+#define bfd_plugin_bfd_link_hash_table_free           _bfd_generic_link_hash_table_free
+#define bfd_plugin_bfd_link_add_symbols               _bfd_generic_link_add_symbols
+#define bfd_plugin_bfd_link_just_syms                 _bfd_generic_link_just_syms
+#define bfd_plugin_bfd_final_link                     _bfd_generic_final_link
+#define bfd_plugin_bfd_link_split_section             _bfd_generic_link_split_section
+#define bfd_plugin_bfd_gc_sections                    bfd_generic_gc_sections
+#define bfd_plugin_bfd_merge_sections                 bfd_generic_merge_sections
+#define bfd_plugin_bfd_is_group_section               bfd_generic_is_group_section
+#define bfd_plugin_bfd_discard_group                  bfd_generic_discard_group
+#define bfd_plugin_section_already_linked             _bfd_generic_section_already_linked
+
+static enum ld_plugin_status
+message(int level ATTRIBUTE_UNUSED,
+	const char * format, ...)
+{
+  va_list args;
+  va_start(args, format);
+  vprintf(format, args);
+  va_end(args);
+  return LDPS_OK;
+}
+
+// Register a claim-file handler.
+static ld_plugin_claim_file_handler claim_file;
+
+static enum ld_plugin_status
+register_claim_file(ld_plugin_claim_file_handler handler)
+{
+  claim_file = handler;
+  return LDPS_OK;
+}
+
+static enum ld_plugin_status
+add_symbols(void* handle, int nsyms,
+	    const struct ld_plugin_symbol *syms)
+{
+  bfd *abfd = handle;
+  struct plugin_data_struct *plugin_data =
+    bfd_alloc(abfd, sizeof (plugin_data_struct));;
+
+  plugin_data->nsyms = nsyms;
+  plugin_data->syms = syms;
+
+  if (nsyms != 0)
+    abfd->flags |= HAS_SYMS;
+
+  abfd->tdata.plugin_data = plugin_data;
+  return LDPS_OK;
+}
+
+static int
+load_plugin(void)
+{
+  static void *plugin_handle;
+  int tv_size = 4;
+  struct ld_plugin_tv tv[tv_size];
+  int i;
+  ld_plugin_onload onload;
+  enum ld_plugin_status status;
+
+  if (plugin_handle)
+    return 1;
+
+  const char *pname = getenv ("BFD_PLUGIN");
+  if (!pname)
+    return 0;
+
+  plugin_handle = dlopen(pname, RTLD_NOW);
+  if (!plugin_handle)
+    {
+      fprintf (stderr, "%s\n", dlerror());
+      return 0;
+    }
+
+  onload = dlsym(plugin_handle, "onload");
+  if (!onload)
+    goto err;
+
+  i = 0;
+  tv[i].tv_tag = LDPT_MESSAGE;
+  tv[i].tv_u.tv_message = message;
+
+  ++i;
+  tv[i].tv_tag = LDPT_REGISTER_CLAIM_FILE_HOOK;
+  tv[i].tv_u.tv_register_claim_file = register_claim_file;
+
+  ++i;
+  tv[i].tv_tag = LDPT_ADD_SYMBOLS;
+  tv[i].tv_u.tv_add_symbols = add_symbols;
+
+  ++i;
+  tv[i].tv_tag = LDPT_NULL;
+  tv[i].tv_u.tv_val = 0;
+
+  status = (*onload)(tv);
+
+  if (status != LDPS_OK)
+    goto err;
+
+  if (!claim_file)
+    goto err;
+
+  return 1;
+
+ err:
+  plugin_handle = NULL;
+  return 0;
+}
+
+static const bfd_target *
+bfd_plugin_object_p (bfd *abfd)
+{
+  int t = load_plugin ();
+  if (!t)
+    return NULL;
+
+  int claimed;
+
+  struct ld_plugin_input_file file;
+  file.name = abfd->filename;
+
+  if (abfd->iostream)
+    {
+      file.fd = fileno (abfd->iostream);
+      file.offset = 0;
+      file.filesize = 0; /*FIXME*/
+    }
+  else
+    {
+      bfd *archive = abfd->my_archive;
+      assert (archive);
+      file.fd = fileno (archive->iostream);
+      file.offset = abfd->origin;
+      file.filesize = arelt_size (abfd);
+
+    }
+  file.handle = abfd;
+  claim_file(&file, &claimed);
+  assert(claimed);
+
+  return abfd->xvec;
+}
+
+/* Copy any private info we understand from the input bfd
+   to the output bfd.  */
+
+static bfd_boolean
+bfd_plugin_bfd_copy_private_bfd_data (bfd *ibfd ATTRIBUTE_UNUSED,
+				      bfd *obfd ATTRIBUTE_UNUSED)
+{
+  assert (0);
+  return TRUE;
+}
+
+/* Copy any private info we understand from the input section
+   to the output section.  */
+
+static bfd_boolean
+bfd_plugin_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
+					  asection *isection ATTRIBUTE_UNUSED,
+					  bfd *obfd ATTRIBUTE_UNUSED,
+					  asection *osection ATTRIBUTE_UNUSED)
+{
+  assert (0);
+  return TRUE;
+}
+
+/* Copy any private info we understand from the input symbol
+   to the output symbol.  */
+
+static bfd_boolean
+bfd_plugin_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
+					 asymbol *isymbol ATTRIBUTE_UNUSED,
+					 bfd *obfd ATTRIBUTE_UNUSED,
+					 asymbol *osymbol ATTRIBUTE_UNUSED)
+{
+  assert (0);
+  return TRUE;
+}
+
+static bfd_boolean
+bfd_plugin_bfd_print_private_bfd_data (bfd *abfd ATTRIBUTE_UNUSED, PTR ptr ATTRIBUTE_UNUSED)
+{
+  assert (0);
+  return TRUE;
+}
+
+static char *
+bfd_plugin_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
+{
+  assert (0);
+  return NULL;
+}
+
+static int
+bfd_plugin_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
+{
+  assert (0);
+  return 0;
+}
+
+static long
+bfd_plugin_get_symtab_upper_bound (bfd *abfd)
+{
+  struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
+  long nsyms = plugin_data->nsyms;
+
+  assert (nsyms >= 0);
+
+  return ((nsyms + 1) * sizeof (asymbol *));
+}
+
+static flagword
+convert_flags (const struct ld_plugin_symbol *sym)
+{
+ switch (sym->def)
+   { 
+   case LDPK_DEF:
+   case LDPK_COMMON:
+   case LDPK_UNDEF:
+     return BSF_GLOBAL;
+
+   case LDPK_WEAKUNDEF:
+     /* currently llvm has no WEAKUNDEF */
+   case LDPK_WEAKDEF:
+     return BSF_GLOBAL | BSF_WEAK;
+
+   default:
+     assert (0);
+   }
+}
+
+static long
+bfd_plugin_canonicalize_symtab (bfd *abfd,
+				asymbol **alocation)
+{
+  struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
+  static asection fake_section;
+  static asection fake_common_section;
+
+  fake_section.name = ".text";
+  fake_common_section.flags = SEC_IS_COMMON;
+
+  long nsyms = plugin_data->nsyms;
+  const struct ld_plugin_symbol *syms = plugin_data->syms;
+  int i;
+  for (i = 0; i < nsyms; i++)
+    {
+      /* Where should we free this?*/
+      asymbol *s = bfd_alloc (abfd, sizeof (asymbol)); 
+
+      assert (s);
+      alocation[i] = s;
+
+      s->the_bfd = abfd;
+      s->name = syms[i].name;
+      s->value = 0;
+      s->flags = convert_flags (&syms[i]);
+      switch (syms[i].def)
+	{
+	case LDPK_COMMON:
+	  s->section = &fake_common_section;
+	  break;
+	case LDPK_UNDEF:
+	case LDPK_WEAKUNDEF:
+	  /* currently llvm has no WEAKUNDEF */
+	  s->section = bfd_und_section_ptr;
+	  break;
+	case LDPK_DEF:
+	case LDPK_WEAKDEF:
+	  s->section = &fake_section;
+	  break;
+	default:
+	  assert (0);
+	}
+
+      s->udata.p = (void *) &syms[i];
+    }
+
+  return nsyms;
+}
+
+static void
+bfd_plugin_print_symbol (bfd *abfd ATTRIBUTE_UNUSED,
+			 PTR afile ATTRIBUTE_UNUSED,
+			 asymbol *symbol ATTRIBUTE_UNUSED,
+			 bfd_print_symbol_type how ATTRIBUTE_UNUSED)
+{
+  assert (0);
+}
+
+static void
+bfd_plugin_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
+			    asymbol *symbol,
+			    symbol_info *ret)
+{
+  bfd_symbol_info (symbol, ret);
+}
+
+/* Make an empty symbol. */
+
+static asymbol *
+bfd_plugin_make_empty_symbol (bfd *abfd)
+{
+  asymbol *new = bfd_zalloc (abfd, sizeof (asymbol));
+  if (new == NULL)
+    return new;
+  new->the_bfd = abfd;
+  return new;
+}
+
+static int
+bfd_plugin_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
+			   struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+  assert (0);
+  return 0;
+}
+
+static bfd_boolean
+bfd_plugin_mkobject (bfd *abfd ATTRIBUTE_UNUSED)
+{
+  assert (0);
+  return 0;
+}
+
+const bfd_target plugin_vec =
+{
+  "plugin",		/* Name.  */
+  bfd_target_unknown_flavour,
+  BFD_ENDIAN_LITTLE,		/* Target byte order.  */
+  BFD_ENDIAN_LITTLE,		/* Target headers byte order.  */
+  (HAS_RELOC | EXEC_P |		/* Object flags.  */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
+   | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
+  0,				/* symbol_leading_char.  */
+  '/',				/* ar_pad_char.  */
+  15,				/* ar_max_namelen.  */
+
+  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+  bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+  bfd_getl16, bfd_getl_signed_16, bfd_putl16,	/* data */
+  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+  bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+  bfd_getl16, bfd_getl_signed_16, bfd_putl16,	/* hdrs */
+
+  {				/* bfd_check_format.  */
+    _bfd_dummy_target,
+    bfd_plugin_object_p,
+    bfd_generic_archive_p,
+    _bfd_dummy_target
+  },
+  {				/* bfd_set_format.  */
+    bfd_false,
+    bfd_plugin_mkobject,
+    _bfd_generic_mkarchive,
+    bfd_false,
+  },
+  {				/* bfd_write_contents.  */
+    bfd_false,
+    bfd_false,
+    _bfd_write_archive_contents,
+    bfd_false,
+  },
+
+  BFD_JUMP_TABLE_GENERIC (bfd_plugin),
+  BFD_JUMP_TABLE_COPY (bfd_plugin),
+  BFD_JUMP_TABLE_CORE (bfd_plugin),
+  BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+  BFD_JUMP_TABLE_SYMBOLS (bfd_plugin),
+  BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
+  BFD_JUMP_TABLE_WRITE (bfd_plugin),
+  BFD_JUMP_TABLE_LINK (bfd_plugin),
+  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+  NULL,
+
+  /* backend_data: */
+  NULL
+};
diff --git a/bfd/plugin.h b/bfd/plugin.h
new file mode 100644
index 0000000..37392b0
--- /dev/null
+++ b/bfd/plugin.h
@@ -0,0 +1,34 @@
+/* Plugin support for BFD.
+   Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2008
+   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.  */
+
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+#include "bfd.h"
+
+typedef struct plugin_data_struct
+{
+  int nsyms;
+  const struct ld_plugin_symbol *syms;
+}
+plugin_data_struct;
+
+#endif
diff --git a/bfd/targets.c b/bfd/targets.c
index 2eab663..bb74943 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -767,6 +767,7 @@ extern const bfd_target pc532netbsd_vec;
 extern const bfd_target pdp11_aout_vec;
 extern const bfd_target pef_vec;
 extern const bfd_target pef_xlib_vec;
+extern const bfd_target plugin_vec;
 extern const bfd_target pmac_xcoff_vec;
 extern const bfd_target ppcboot_vec;
 extern const bfd_target riscix_vec;
@@ -1149,6 +1150,7 @@ static const bfd_target * const _bfd_target_vector[] =
 	&pdp11_aout_vec,
 	&pef_vec,
 	&pef_xlib_vec,
+	&plugin_vec,
 #if 0
 	/* This has the same magic number as RS/6000.  */
 	&pmac_xcoff_vec,
diff --git a/binutils/Makefile.am b/binutils/Makefile.am
index 738ae75..1ff0f0e 100644
--- a/binutils/Makefile.am
+++ b/binutils/Makefile.am
@@ -22,6 +22,10 @@ NO_WERROR = @NO_WERROR@
 AM_CFLAGS = $(WARN_CFLAGS)
 LIBICONV = @LIBICONV@
 
+if PLUGINS
+LIBDL = -ldl
+endif
+
 # these two are almost the same program
 AR_PROG=ar
 RANLIB_PROG=ranlib
@@ -235,7 +239,7 @@ addr2line_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
 readelf_DEPENDENCIES =   $(LIBINTL_DEP) $(LIBIBERTY)
 dllwrap_DEPENDENCIES =   $(LIBINTL_DEP) $(LIBIBERTY)
 
-LDADD = $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
+LDADD = $(BFDLIB) $(LIBIBERTY) $(LIBINTL) $(LIBDL)
 
 size_SOURCES = size.c $(BULIBS)
 
@@ -251,7 +255,7 @@ strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS)
 nm_new_SOURCES = nm.c $(BULIBS)
 
 objdump_SOURCES = objdump.c dwarf.c prdbg.c $(DEBUG_SRCS) $(BULIBS)
-objdump_LDADD = $(OPCODES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
+objdump_LDADD = $(OPCODES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL) $(LIBDL)
 
 objdump.o:objdump.c
 	$(COMPILE) -c $(OBJDUMP_DEFS) $(srcdir)/objdump.c
@@ -260,11 +264,11 @@ cxxfilt_SOURCES = cxxfilt.c $(BULIBS)
 
 ar_SOURCES = arparse.y arlex.l ar.c not-ranlib.c arsup.c rename.c binemul.c \
 	emul_$(EMULATION).c $(BULIBS)
-ar_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(LIBINTL)
+ar_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(LIBINTL) $(LIBDL)
 
 ranlib_SOURCES = ar.c is-ranlib.c arparse.y arlex.l arsup.c rename.c \
 	binemul.c emul_$(EMULATION).c $(BULIBS)
-ranlib_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(LIBINTL)
+ranlib_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(LIBINTL) $(LIBDL)
 
 addr2line_SOURCES = addr2line.c $(BULIBS)
 
diff --git a/binutils/ar.c b/binutils/ar.c
index f493221..f984537 100644
--- a/binutils/ar.c
+++ b/binutils/ar.c
@@ -361,6 +361,7 @@ main (int argc, char **argv)
   int show_version;
   int i;
   int do_posix = 0;
+  char *plugin = NULL;
 
 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
   setlocale (LC_MESSAGES, "");
@@ -474,6 +475,18 @@ main (int argc, char **argv)
   arg_index = 1;
   arg_ptr = argv[arg_index];
 
+  if (strcmp (arg_ptr, "--plugin") == 0)
+    {
+      if (argc < 4)
+	usage(1);
+
+      asprintf(&plugin, "BFD_PLUGIN=%s", argv[2]);
+      putenv(plugin);
+
+      arg_index += 2;
+      arg_ptr = argv[arg_index];
+    }
+
   if (*arg_ptr == '-')
     {
       /* When the first option starts with '-' we support POSIX-compatible
@@ -690,6 +703,8 @@ main (int argc, char **argv)
 
   END_PROGRESS (program_name);
 
+  if (plugin)
+    free (plugin);
   xexit (0);
   return 0;
 }
diff --git a/binutils/configure.in b/binutils/configure.in
index 8a2c345..257847a 100644
--- a/binutils/configure.in
+++ b/binutils/configure.in
@@ -47,6 +47,17 @@ AM_PO_SUBDIRS
 
 AM_MAINTAINER_MODE
 AM_CONDITIONAL(GENINSRC_NEVER, false)
+AC_ARG_ENABLE([plugins],
+[  --enable-plugins        linker plugins],
+[case "${enableval}" in
+  yes | "") plugins=yes ;;
+  no) plugins=no ;;
+  *) plugins=yes ;;
+ esac],
+[plugins=no])
+
+AM_CONDITIONAL(PLUGINS, test "$plugins" = "yes")
+
 AC_EXEEXT
 if test -n "$EXEEXT"; then
   AC_DEFINE(HAVE_EXECUTABLE_SUFFIX, 1,
diff --git a/binutils/nm.c b/binutils/nm.c
index e11568a..aa315cf 100644
--- a/binutils/nm.c
+++ b/binutils/nm.c
@@ -178,6 +178,7 @@ static bfd *lineno_cache_bfd;
 static bfd *lineno_cache_rel_bfd;
 
 #define OPTION_TARGET 200
+#define OPTION_PLUGIN 201
 
 static struct option long_options[] =
 {
@@ -192,6 +193,7 @@ static struct option long_options[] =
   {"no-demangle", no_argument, &do_demangle, 0},
   {"no-sort", no_argument, &no_sort, 1},
   {"numeric-sort", no_argument, &sort_numerically, 1},
+  {"plugin", required_argument, 0, OPTION_PLUGIN},
   {"portability", no_argument, 0, 'P'},
   {"print-armap", no_argument, &print_armap, 1},
   {"print-file-name", no_argument, 0, 'o'},
@@ -1496,6 +1498,7 @@ main (int argc, char **argv)
 {
   int c;
   int retval;
+  char *plugin = NULL;
 
 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
   setlocale (LC_MESSAGES, "");
@@ -1608,6 +1611,18 @@ main (int argc, char **argv)
 	  target = optarg;
 	  break;
 
+	case OPTION_PLUGIN:	/* --plugin */
+	  {
+	    if (plugin)
+	      {
+		free (plugin);
+		usage (stderr, 1);
+	      }
+	    asprintf(&plugin, "BFD_PLUGIN=%s", optarg);
+	    putenv(plugin);
+	  }
+	  break;
+
 	case 0:		/* A long option that just sets a flag.  */
 	  break;
 
@@ -1654,6 +1669,8 @@ main (int argc, char **argv)
     }
 #endif
 
+  if (plugin)
+    free (plugin);
   exit (retval);
   return retval;
 }
diff --git a/gas/Makefile.am b/gas/Makefile.am
index 228624e..21f011e 100644
--- a/gas/Makefile.am
+++ b/gas/Makefile.am
@@ -499,6 +499,10 @@ BASEDIR = $(srcdir)/..
 BFDDIR = $(BASEDIR)/bfd
 INCDIR = $(BASEDIR)/include
 
+if PLUGINS
+LIBDL = -ldl
+endif
+
 # This is the variable actually used when we compile.
 # Specify the directories to be searched for header files.
 # Both . and srcdir are used, in that order,
@@ -530,7 +534,7 @@ STAGESTUFF = *.o $(noinst_PROGRAMS)
 
 as_new_SOURCES = $(GAS_CFILES)
 as_new_LDADD = $(TARG_CPU_O) $(OBJ_FORMAT_O) $(ATOF_TARG_O) \
-	$(extra_objects) $(GASLIBS) $(LIBINTL) $(LIBM)
+	$(extra_objects) $(GASLIBS) $(LIBINTL) $(LIBM) $(LIBDL)
 as_new_DEPENDENCIES = $(TARG_CPU_O) $(OBJ_FORMAT_O) $(ATOF_TARG_O) \
 	$(extra_objects) $(GASLIBS) $(LIBINTL_DEP)
 
diff --git a/gas/configure.in b/gas/configure.in
index 242bac7..ff75770 100644
--- a/gas/configure.in
+++ b/gas/configure.in
@@ -602,6 +602,16 @@ AM_PO_SUBDIRS
 
 AM_MAINTAINER_MODE
 AM_CONDITIONAL(GENINSRC_NEVER, false)
+AC_ARG_ENABLE([plugins],
+[  --enable-plugins        linker plugins],
+[case "${enableval}" in
+  yes | "") plugins=yes ;;
+  no) plugins=no ;;
+  *) plugins=yes ;;
+ esac],
+[plugins=no])
+
+AM_CONDITIONAL(PLUGINS, test "$plugins" = "yes")
 AC_EXEEXT
 
 AC_CHECK_HEADERS(string.h stdlib.h memory.h strings.h unistd.h stdarg.h varargs.h errno.h sys/types.h limits.h)
diff --git a/gprof/Makefile.am b/gprof/Makefile.am
index 1613c04..aa464a9 100644
--- a/gprof/Makefile.am
+++ b/gprof/Makefile.am
@@ -15,6 +15,10 @@ WARN_CFLAGS = @WARN_CFLAGS@
 NO_WERROR = @NO_WERROR@
 AM_CFLAGS = $(WARN_CFLAGS)
 
+if PLUGINS
+LIBDL = -ldl
+endif
+
 MKDEP = gcc -MM
 
 INCLUDES = -DDEBUG -I../bfd -I$(srcdir)/../include \
@@ -30,7 +34,7 @@ sources = basic_blocks.c call_graph.c cg_arcs.c cg_dfn.c \
 	i386.c alpha.c vax.c tahoe.c sparc.c mips.c
 gprof_SOURCES = $(sources) flat_bl.c bsd_callg_bl.c fsf_callg_bl.c
 gprof_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a $(LIBINTL_DEP)
-gprof_LDADD = ../bfd/libbfd.la ../libiberty/libiberty.a $(LIBINTL)
+gprof_LDADD = ../bfd/libbfd.la ../libiberty/libiberty.a $(LIBINTL) $(LIBDL)
 
 noinst_HEADERS = \
 	basic_blocks.h call_graph.h cg_arcs.h cg_dfn.h cg_print.h \
diff --git a/gprof/configure.in b/gprof/configure.in
index 1ee8064..c1dec91 100644
--- a/gprof/configure.in
+++ b/gprof/configure.in
@@ -33,6 +33,16 @@ AM_PO_SUBDIRS
 
 AM_MAINTAINER_MODE
 AM_CONDITIONAL(GENINSRC_NEVER, false)
+AC_ARG_ENABLE([plugins],
+[  --enable-plugins        linker plugins],
+[case "${enableval}" in
+  yes | "") plugins=yes ;;
+  no) plugins=no ;;
+  *) plugins=yes ;;
+ esac],
+[plugins=no])
+
+AM_CONDITIONAL(PLUGINS, test "$plugins" = "yes")
 AC_EXEEXT
 
 AC_CHECK_HEADERS(sys/gmon_out.h)
diff --git a/ld/Makefile.am b/ld/Makefile.am
index 806168e..a660119 100644
--- a/ld/Makefile.am
+++ b/ld/Makefile.am
@@ -108,6 +108,10 @@ INCLUDES = -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) \
 BFDLIB = ../bfd/libbfd.la
 LIBIBERTY = ../libiberty/libiberty.a
 
+if PLUGINS
+LIBDL = -ldl
+endif
+
 ALL_EMULATIONS = \
 	eaixppc.o \
 	eaixrs6.o \
@@ -1739,7 +1743,7 @@ EXTRA_ld_new_SOURCES = deffilep.y
 ld_new_SOURCES = ldgram.y ldlex.l lexsup.c ldlang.c mri.c ldctor.c ldmain.c \
 	ldwrite.c ldexp.c ldemul.c ldver.c ldmisc.c ldfile.c ldcref.c
 ld_new_DEPENDENCIES = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL_DEP)
-ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
+ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL) $(LIBDL)
 
 # The generated emulation files mostly have the same dependencies.
 $(EMULATION_OFILES): ../bfd/bfd.h sysdep.h config.h $(INCDIR)/bfdlink.h \
diff --git a/ld/configure.in b/ld/configure.in
index 2df309a..a63069d 100644
--- a/ld/configure.in
+++ b/ld/configure.in
@@ -126,6 +126,17 @@ AM_PROG_LEX
 AM_MAINTAINER_MODE
 AM_CONDITIONAL(GENINSRC_NEVER, false)
 
+AC_ARG_ENABLE([plugins],
+[  --enable-plugins        linker plugins],
+[case "${enableval}" in
+  yes | "") plugins=yes ;;
+  no) plugins=no ;;
+  *) plugins=yes ;;
+ esac],
+[plugins=no])
+
+AM_CONDITIONAL(PLUGINS, test "$plugins" = "yes")
+
 . ${srcdir}/configure.host
 
 AC_SUBST(HDEFINES)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]