OSDN Git Service

daily update
[pf3gnuchains/pf3gnuchains3x.git] / bfd / bfd.c
index c4b18e9..eef9f36 100644 (file)
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -1,6 +1,6 @@
 /* Generic BFD library interface and support routines.
    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2006
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Written by Cygnus Support.
 
@@ -8,7 +8,7 @@
 
    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 2 of the License, or
+   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,
@@ -18,7 +18,8 @@
 
    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.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 /*
 SECTION
@@ -34,6 +35,14 @@ SECTION
 
 CODE_FRAGMENT
 .
+.enum bfd_direction
+.  {
+.    no_direction = 0,
+.    read_direction = 1,
+.    write_direction = 2,
+.    both_direction = 3
+.  };
+.
 .struct bfd
 .{
 .  {* A unique identifier of the BFD  *}
@@ -50,15 +59,6 @@ CODE_FRAGMENT
 .  void *iostream;
 .  const struct bfd_iovec *iovec;
 .
-.  {* Is the file descriptor being cached?  That is, can it be closed as
-.     needed, and re-opened when accessed later?  *}
-.  bfd_boolean cacheable;
-.
-.  {* Marks whether there was a default target specified when the
-.     BFD was opened. This is used to select which matching algorithm
-.     to use to choose the back end.  *}
-.  bfd_boolean target_defaulted;
-.
 .  {* The caching routines use these to maintain a
 .     least-recently-used list of BFDs.  *}
 .  struct bfd *lru_prev, *lru_next;
@@ -67,13 +67,6 @@ CODE_FRAGMENT
 .     state information on the file here...  *}
 .  ufile_ptr where;
 .
-.  {* ... and here: (``once'' means at least once).  *}
-.  bfd_boolean opened_once;
-.
-.  {* Set if we have a locally maintained mtime value, rather than
-.     getting it from the file each time.  *}
-.  bfd_boolean mtime_set;
-.
 .  {* File modified time, if mtime_set is TRUE.  *}
 .  long mtime;
 .
@@ -84,26 +77,91 @@ CODE_FRAGMENT
 .  bfd_format format;
 .
 .  {* The direction with which the BFD was opened.  *}
-.  enum bfd_direction
-.    {
-.      no_direction = 0,
-.      read_direction = 1,
-.      write_direction = 2,
-.      both_direction = 3
-.    }
-.  direction;
+.  enum bfd_direction direction;
 .
 .  {* Format_specific flags.  *}
 .  flagword flags;
 .
+.  {* Values that may appear in the flags field of a BFD.  These also
+.     appear in the object_flags field of the bfd_target structure, where
+.     they indicate the set of flags used by that backend (not all flags
+.     are meaningful for all object file formats) (FIXME: at the moment,
+.     the object_flags values have mostly just been copied from backend
+.     to another, and are not necessarily correct).  *}
+.
+.#define BFD_NO_FLAGS  0x00
+.
+.  {* BFD contains relocation entries.  *}
+.#define HAS_RELOC     0x01
+.
+.  {* BFD is directly executable.  *}
+.#define EXEC_P        0x02
+.
+.  {* BFD has line number information (basically used for F_LNNO in a
+.     COFF header).  *}
+.#define HAS_LINENO    0x04
+.
+.  {* BFD has debugging information.  *}
+.#define HAS_DEBUG     0x08
+.
+.  {* BFD has symbols.  *}
+.#define HAS_SYMS      0x10
+.
+.  {* BFD has local symbols (basically used for F_LSYMS in a COFF
+.     header).  *}
+.#define HAS_LOCALS    0x20
+.
+.  {* BFD is a dynamic object.  *}
+.#define DYNAMIC       0x40
+.
+.  {* Text section is write protected (if D_PAGED is not set, this is
+.     like an a.out NMAGIC file) (the linker sets this by default, but
+.     clears it for -r or -N).  *}
+.#define WP_TEXT       0x80
+.
+.  {* BFD is dynamically paged (this is like an a.out ZMAGIC file) (the
+.     linker sets this by default, but clears it for -r or -n or -N).  *}
+.#define D_PAGED       0x100
+.
+.  {* BFD is relaxable (this means that bfd_relax_section may be able to
+.     do something) (sometimes bfd_relax_section can do something even if
+.     this is not set).  *}
+.#define BFD_IS_RELAXABLE 0x200
+.
+.  {* This may be set before writing out a BFD to request using a
+.     traditional format.  For example, this is used to request that when
+.     writing out an a.out object the symbols not be hashed to eliminate
+.     duplicates.  *}
+.#define BFD_TRADITIONAL_FORMAT 0x400
+.
+.  {* This flag indicates that the BFD contents are actually cached
+.     in memory.  If this is set, iostream points to a bfd_in_memory
+.     struct.  *}
+.#define BFD_IN_MEMORY 0x800
+.
+.  {* The sections in this BFD specify a memory page.  *}
+.#define HAS_LOAD_PAGE 0x1000
+.
+.  {* This BFD has been created by the linker and doesn't correspond
+.     to any input file.  *}
+.#define BFD_LINKER_CREATED 0x2000
+.
+.  {* This may be set before writing out a BFD to request that it
+.     be written using values for UIDs, GIDs, timestamps, etc. that
+.     will be consistent from run to run.  *}
+.#define BFD_DETERMINISTIC_OUTPUT 0x4000
+.
 .  {* Currently my_archive is tested before adding origin to
 .     anything. I believe that this can become always an add of
 .     origin, with origin set to 0 for non archive files.  *}
 .  ufile_ptr origin;
 .
-.  {* Remember when output has begun, to stop strange things
-.     from happening.  *}
-.  bfd_boolean output_has_begun;
+.  {* The origin in the archive of the proxy entry.  This will
+.     normally be the same as origin, except for thin archives,
+.     when it will contain the current offset of the proxy in the
+.     thin archive rather than the offset of the bfd in its actual
+.     container.  *}
+.  ufile_ptr proxy_origin;
 .
 .  {* A hash table for section names.  *}
 .  struct bfd_hash_table section_htab;
@@ -124,7 +182,8 @@ CODE_FRAGMENT
 .  {* Used for input and output.  *}
 .  unsigned int symcount;
 .
-.  {* Symbol table for output BFD (with symcount entries).  *}
+.  {* Symbol table for output BFD (with symcount entries).
+.     Also used by the linker to cache input BFD symbols.  *}
 .  struct bfd_symbol  **outsymbols;
 .
 .  {* Used for slurped dynamic symbol tables.  *}
@@ -133,15 +192,13 @@ CODE_FRAGMENT
 .  {* Pointer to structure which contains architecture information.  *}
 .  const struct bfd_arch_info *arch_info;
 .
-.  {* Flag set if symbols from this BFD should not be exported.  *}
-.  bfd_boolean no_export;
-.
 .  {* Stuff only useful for archives.  *}
 .  void *arelt_data;
 .  struct bfd *my_archive;      {* The containing archive BFD.  *}
-.  struct bfd *next;            {* The next BFD in the archive.  *}
+.  struct bfd *archive_next;    {* The next BFD in the archive.  *}
 .  struct bfd *archive_head;    {* The first BFD in the archive.  *}
-.  bfd_boolean has_armap;
+.  struct bfd *nested_archives; {* List of nested archive in a flattened
+.                                  thin archive.  *}
 .
 .  {* A chain of BFD structures involved in a link.  *}
 .  struct bfd *link_next;
@@ -164,6 +221,7 @@ CODE_FRAGMENT
 .      struct ieee_data_struct *ieee_data;
 .      struct ieee_ar_data_struct *ieee_ar_data;
 .      struct srec_data_struct *srec_data;
+.      struct verilog_data_struct *verilog_data;
 .      struct ihex_data_struct *ihex_data;
 .      struct tekhex_data_struct *tekhex_data;
 .      struct elf_obj_tdata *elf_obj_data;
@@ -184,6 +242,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;
@@ -198,15 +257,45 @@ CODE_FRAGMENT
 .     struct objalloc *, but we use void * to avoid requiring the inclusion
 .     of objalloc.h.  *}
 .  void *memory;
+.
+.  {* Is the file descriptor being cached?  That is, can it be closed as
+.     needed, and re-opened when accessed later?  *}
+.  unsigned int cacheable : 1;
+.
+.  {* Marks whether there was a default target specified when the
+.     BFD was opened. This is used to select which matching algorithm
+.     to use to choose the back end.  *}
+.  unsigned int target_defaulted : 1;
+.
+.  {* ... and here: (``once'' means at least once).  *}
+.  unsigned int opened_once : 1;
+.
+.  {* Set if we have a locally maintained mtime value, rather than
+.     getting it from the file each time.  *}
+.  unsigned int mtime_set : 1;
+.
+.  {* Flag set if symbols from this BFD should not be exported.  *}
+.  unsigned int no_export : 1;
+.
+.  {* Remember when output has begun, to stop strange things
+.     from happening.  *}
+.  unsigned int output_has_begun : 1;
+.
+.  {* Have archive map.  *}
+.  unsigned int has_armap : 1;
+.
+.  {* Set if this is a thin archive.  *}
+.  unsigned int is_thin_archive : 1;
 .};
 .
 */
 
-#include "bfd.h"
-#include "bfdver.h"
 #include "sysdep.h"
 #include <stdarg.h>
+#include "bfd.h"
+#include "bfdver.h"
 #include "libiberty.h"
+#include "demangle.h"
 #include "safe-ctype.h"
 #include "bfdlink.h"
 #include "libbfd.h"
@@ -271,6 +360,7 @@ CODE_FRAGMENT
 .  bfd_error_bad_value,
 .  bfd_error_file_truncated,
 .  bfd_error_file_too_big,
+.  bfd_error_on_input,
 .  bfd_error_invalid_error_code
 .}
 .bfd_error_type;
@@ -278,6 +368,8 @@ CODE_FRAGMENT
 */
 
 static bfd_error_type bfd_error = bfd_error_no_error;
+static bfd *input_bfd = NULL;
+static bfd_error_type input_error = bfd_error_no_error;
 
 const char *const bfd_errmsgs[] =
 {
@@ -300,6 +392,7 @@ const char *const bfd_errmsgs[] =
   N_("Bad value"),
   N_("File truncated"),
   N_("File too big"),
+  N_("Error reading %s: %s"),
   N_("#<Invalid error code>")
 };
 
@@ -325,16 +418,32 @@ FUNCTION
        bfd_set_error
 
 SYNOPSIS
-       void bfd_set_error (bfd_error_type error_tag);
+       void bfd_set_error (bfd_error_type error_tag, ...);
 
 DESCRIPTION
        Set the BFD error condition to be @var{error_tag}.
+       If @var{error_tag} is bfd_error_on_input, then this function
+       takes two more parameters, the input bfd where the error
+       occurred, and the bfd_error_type error.
 */
 
 void
-bfd_set_error (bfd_error_type error_tag)
+bfd_set_error (bfd_error_type error_tag, ...)
 {
   bfd_error = error_tag;
+  if (error_tag == bfd_error_on_input)
+    {
+      /* This is an error that occurred during bfd_close when
+        writing an archive, but on one of the input files.  */
+      va_list ap;
+
+      va_start (ap, error_tag);
+      input_bfd = va_arg (ap, bfd *);
+      input_error = (bfd_error_type) va_arg (ap, int);
+      if (input_error >= bfd_error_on_input)
+       abort ();
+      va_end (ap);
+    }
 }
 
 /*
@@ -355,6 +464,19 @@ bfd_errmsg (bfd_error_type error_tag)
 #ifndef errno
   extern int errno;
 #endif
+  if (error_tag == bfd_error_on_input)
+    {
+      char *buf;
+      const char *msg = bfd_errmsg (input_error);
+
+      if (asprintf (&buf, _(bfd_errmsgs [error_tag]), input_bfd->filename, msg)
+         != -1)
+       return buf;
+
+      /* Ick, what to do on out of memory?  */
+      return msg;
+    }
+
   if (error_tag == bfd_error_system_call)
     return xstrerror (errno);
 
@@ -382,16 +504,10 @@ DESCRIPTION
 void
 bfd_perror (const char *message)
 {
-  if (bfd_get_error () == bfd_error_system_call)
-    /* Must be a system error then.  */
-    perror ((char *) message);
+  if (message == NULL || *message == '\0')
+    fprintf (stderr, "%s\n", bfd_errmsg (bfd_get_error ()));
   else
-    {
-      if (message == NULL || *message == '\0')
-       fprintf (stderr, "%s\n", bfd_errmsg (bfd_get_error ()));
-      else
-       fprintf (stderr, "%s: %s\n", message, bfd_errmsg (bfd_get_error ()));
-    }
+    fprintf (stderr, "%s: %s\n", message, bfd_errmsg (bfd_get_error ()));
 }
 
 /*
@@ -419,6 +535,23 @@ static const char *_bfd_error_program_name;
 
    %A section name from section.  For group components, print group name too.
    %B file name from bfd.  For archive components, prints archive too.
+
+   Note - because these two extra format specifiers require special handling
+   they are scanned for and processed in this function, before calling
+   vfprintf.  This means that the *arguments* for these format specifiers
+   must be the first ones in the variable argument list, regardless of where
+   the specifiers appear in the format string.  Thus for example calling
+   this function with a format string of:
+
+      "blah %s blah %A blah %d blah %B"
+
+   would involve passing the arguments as:
+
+      "blah %s blah %A blah %d blah %B",
+        asection_for_the_%A,
+       bfd_for_the_%B,
+       string_for_the_%s,
+       integer_for_the_%d);
  */
 
 void
@@ -430,6 +563,9 @@ _bfd_default_error_handler (const char *fmt, ...)
   size_t avail = 1000;
   char buf[1000];
 
+  /* PR 4992: Don't interrupt output being sent to stdout.  */
+  fflush (stdout);
+
   if (_bfd_error_program_name != NULL)
     fprintf (stderr, "%s: ", _bfd_error_program_name);
   else
@@ -483,7 +619,11 @@ _bfd_default_error_handler (const char *fmt, ...)
              if (p[1] == 'B')
                {
                  bfd *abfd = va_arg (ap, bfd *);
-                 if (abfd->my_archive)
+
+                 if (abfd == NULL)
+                   /* Invoking %B with a null bfd pointer is an internal error.  */
+                   abort ();
+                 else if (abfd->my_archive)
                    snprintf (bufp, avail, "%s(%s)",
                              abfd->my_archive->filename, abfd->filename);
                  else
@@ -492,10 +632,14 @@ _bfd_default_error_handler (const char *fmt, ...)
              else
                {
                  asection *sec = va_arg (ap, asection *);
-                 bfd *abfd = sec->owner;
+                 bfd *abfd;
                  const char *group = NULL;
                  struct coff_comdat_info *ci;
 
+                 if (sec == NULL)
+                   /* Invoking %A with a null section pointer is an internal error.  */
+                   abort ();
+                 abfd = sec->owner;
                  if (abfd != NULL
                      && bfd_get_flavour (abfd) == bfd_target_elf_flavour
                      && elf_next_in_group (sec) != NULL
@@ -851,16 +995,23 @@ bfd_get_sign_extend_vma (bfd *abfd)
 
   name = bfd_get_target (abfd);
 
-  /* Return a proper value for DJGPP & PE COFF (x86 COFF variants).
+  /* Return a proper value for DJGPP & PE COFF.
      This function is required for DWARF2 support, but there is
      no place to store this information in the COFF back end.
      Should enough other COFF targets add support for DWARF2,
      a place will have to be found.  Until then, this hack will do.  */
-  if (strncmp (name, "coff-go32", sizeof ("coff-go32") - 1) == 0
+  if (CONST_STRNEQ (name, "coff-go32")
       || strcmp (name, "pe-i386") == 0
-      || strcmp (name, "pei-i386") == 0)
+      || strcmp (name, "pei-i386") == 0
+      || strcmp (name, "pe-x86-64") == 0
+      || strcmp (name, "pei-x86-64") == 0
+      || strcmp (name, "pe-arm-wince-little") == 0
+      || strcmp (name, "pei-arm-wince-little") == 0)
     return 1;
 
+  if (CONST_STRNEQ (name, "mach-o"))
+    return 0;
+
   bfd_set_error (bfd_error_wrong_format);
   return -1;
 }
@@ -964,7 +1115,7 @@ void
 _bfd_set_gp_value (bfd *abfd, bfd_vma v)
 {
   if (! abfd)
-    BFD_FAIL ();
+    abort ();
   if (abfd->format != bfd_object)
     return;
 
@@ -1158,8 +1309,8 @@ FUNCTION
 DESCRIPTION
        The following functions exist but have not yet been documented.
 
-.#define bfd_sizeof_headers(abfd, reloc) \
-.       BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
+.#define bfd_sizeof_headers(abfd, info) \
+.       BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, info))
 .
 .#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \
 .       BFD_SEND (abfd, _bfd_find_nearest_line, \
@@ -1298,11 +1449,10 @@ bfd_record_phdr (bfd *abfd,
 
   amt = sizeof (struct elf_segment_map);
   amt += ((bfd_size_type) count - 1) * sizeof (asection *);
-  m = bfd_alloc (abfd, amt);
+  m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
   if (m == NULL)
     return FALSE;
 
-  m->next = NULL;
   m->p_type = type;
   m->p_flags = flags;
   m->p_paddr = at;
@@ -1321,22 +1471,50 @@ bfd_record_phdr (bfd *abfd,
   return TRUE;
 }
 
-void
-bfd_sprintf_vma (bfd *abfd, char *buf, bfd_vma value)
+#ifdef BFD64
+/* Return true iff this target is 32-bit.  */
+
+static bfd_boolean
+is32bit (bfd *abfd)
 {
   if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
-    get_elf_backend_data (abfd)->elf_backend_sprintf_vma (abfd, buf, value);
-  else
-    sprintf_vma (buf, value);
+    {
+      const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+      return bed->s->elfclass == ELFCLASS32;
+    }
+
+  /* For non-ELF targets, use architecture information.  */
+  return bfd_arch_bits_per_address (abfd) <= 32;
+}
+#endif
+
+/* bfd_sprintf_vma and bfd_fprintf_vma display an address in the
+   target's address size.  */
+
+void
+bfd_sprintf_vma (bfd *abfd ATTRIBUTE_UNUSED, char *buf, bfd_vma value)
+{
+#ifdef BFD64
+  if (is32bit (abfd))
+    {
+      sprintf (buf, "%08lx", (unsigned long) value & 0xffffffff);
+      return;
+    }
+#endif
+  sprintf_vma (buf, value);
 }
 
 void
-bfd_fprintf_vma (bfd *abfd, void *stream, bfd_vma value)
+bfd_fprintf_vma (bfd *abfd ATTRIBUTE_UNUSED, void *stream, bfd_vma value)
 {
-  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
-    get_elf_backend_data (abfd)->elf_backend_fprintf_vma (abfd, stream, value);
-  else
-    fprintf_vma ((FILE *) stream, value);
+#ifdef BFD64
+  if (is32bit (abfd))
+    {
+      fprintf ((FILE *) stream, "%08lx", (unsigned long) value & 0xffffffff);
+      return;
+    }
+#endif
+  fprintf_vma ((FILE *) stream, value);
 }
 
 /*
@@ -1440,7 +1618,8 @@ bfd_preserve_save (bfd *abfd, struct bfd_preserve *preserve)
   preserve->section_count = abfd->section_count;
   preserve->section_htab = abfd->section_htab;
 
-  if (! bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc))
+  if (! bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc,
+                            sizeof (struct section_hash_entry)))
     return FALSE;
 
   abfd->tdata.any = NULL;
@@ -1512,3 +1691,222 @@ bfd_preserve_finish (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_preserve *preserve)
      objalloc.  */
   bfd_hash_table_free (&preserve->section_htab);
 }
+
+/*
+FUNCTION
+       bfd_emul_get_maxpagesize
+
+SYNOPSIS
+       bfd_vma bfd_emul_get_maxpagesize (const char *);
+
+DESCRIPTION
+       Returns the maximum page size, in bytes, as determined by
+       emulation.
+
+RETURNS
+       Returns the maximum page size in bytes for ELF, 0 otherwise.
+*/
+
+bfd_vma
+bfd_emul_get_maxpagesize (const char *emul)
+{
+  const bfd_target *target;
+
+  target = bfd_find_target (emul, NULL);
+  if (target != NULL
+      && target->flavour == bfd_target_elf_flavour)
+    return xvec_get_elf_backend_data (target)->maxpagesize;
+
+  return 0;
+}
+
+static void
+bfd_elf_set_pagesize (const bfd_target *target, bfd_vma size,
+                     int offset, const bfd_target *orig_target)
+{
+  if (target->flavour == bfd_target_elf_flavour)
+    {
+      const struct elf_backend_data *bed;
+
+      bed = xvec_get_elf_backend_data (target);
+      *((bfd_vma *) ((char *) bed + offset)) = size;
+    }
+
+  if (target->alternative_target
+      && target->alternative_target != orig_target)
+    bfd_elf_set_pagesize (target->alternative_target, size, offset,
+                         orig_target);
+}
+
+/*
+FUNCTION
+       bfd_emul_set_maxpagesize
+
+SYNOPSIS
+       void bfd_emul_set_maxpagesize (const char *, bfd_vma);
+
+DESCRIPTION
+       For ELF, set the maximum page size for the emulation.  It is
+       a no-op for other formats.
+
+*/
+
+void
+bfd_emul_set_maxpagesize (const char *emul, bfd_vma size)
+{
+  const bfd_target *target;
+
+  target = bfd_find_target (emul, NULL);
+  if (target)
+    bfd_elf_set_pagesize (target, size,
+                         offsetof (struct elf_backend_data,
+                                   maxpagesize), target);
+}
+
+/*
+FUNCTION
+       bfd_emul_get_commonpagesize
+
+SYNOPSIS
+       bfd_vma bfd_emul_get_commonpagesize (const char *);
+
+DESCRIPTION
+       Returns the common page size, in bytes, as determined by
+       emulation.
+
+RETURNS
+       Returns the common page size in bytes for ELF, 0 otherwise.
+*/
+
+bfd_vma
+bfd_emul_get_commonpagesize (const char *emul)
+{
+  const bfd_target *target;
+
+  target = bfd_find_target (emul, NULL);
+  if (target != NULL
+      && target->flavour == bfd_target_elf_flavour)
+    return xvec_get_elf_backend_data (target)->commonpagesize;
+
+  return 0;
+}
+
+/*
+FUNCTION
+       bfd_emul_set_commonpagesize
+
+SYNOPSIS
+       void bfd_emul_set_commonpagesize (const char *, bfd_vma);
+
+DESCRIPTION
+       For ELF, set the common page size for the emulation.  It is
+       a no-op for other formats.
+
+*/
+
+void
+bfd_emul_set_commonpagesize (const char *emul, bfd_vma size)
+{
+  const bfd_target *target;
+
+  target = bfd_find_target (emul, NULL);
+  if (target)
+    bfd_elf_set_pagesize (target, size,
+                         offsetof (struct elf_backend_data,
+                                   commonpagesize), target);
+}
+
+/*
+FUNCTION
+       bfd_demangle
+
+SYNOPSIS
+       char *bfd_demangle (bfd *, const char *, int);
+
+DESCRIPTION
+       Wrapper around cplus_demangle.  Strips leading underscores and
+       other such chars that would otherwise confuse the demangler.
+       If passed a g++ v3 ABI mangled name, returns a buffer allocated
+       with malloc holding the demangled name.  Returns NULL otherwise
+       and on memory alloc failure.
+*/
+
+char *
+bfd_demangle (bfd *abfd, const char *name, int options)
+{
+  char *res, *alloc;
+  const char *pre, *suf;
+  size_t pre_len;
+  bfd_boolean skip_lead;
+
+  skip_lead = (abfd != NULL
+              && *name != '\0'
+              && bfd_get_symbol_leading_char (abfd) == *name);
+  if (skip_lead)
+    ++name;
+
+  /* This is a hack for better error reporting on XCOFF, PowerPC64-ELF
+     or the MS PE format.  These formats have a number of leading '.'s
+     on at least some symbols, so we remove all dots to avoid
+     confusing the demangler.  */
+  pre = name;
+  while (*name == '.' || *name == '$')
+    ++name;
+  pre_len = name - pre;
+
+  /* Strip off @plt and suchlike too.  */
+  alloc = NULL;
+  suf = strchr (name, '@');
+  if (suf != NULL)
+    {
+      alloc = (char *) bfd_malloc (suf - name + 1);
+      if (alloc == NULL)
+       return NULL;
+      memcpy (alloc, name, suf - name);
+      alloc[suf - name] = '\0';
+      name = alloc;
+    }
+
+  res = cplus_demangle (name, options);
+
+  if (alloc != NULL)
+    free (alloc);
+
+  if (res == NULL)
+    {
+      if (skip_lead)
+       {
+         size_t len = strlen (pre) + 1;
+         alloc = (char *) bfd_malloc (len);
+         if (alloc == NULL)
+           return NULL;
+         memcpy (alloc, pre, len);
+         return alloc;
+       }
+      return NULL;
+    }
+
+  /* Put back any prefix or suffix.  */
+  if (pre_len != 0 || suf != NULL)
+    {
+      size_t len;
+      size_t suf_len;
+      char *final;
+
+      len = strlen (res);
+      if (suf == NULL)
+       suf = res + len;
+      suf_len = strlen (suf) + 1;
+      final = (char *) bfd_malloc (pre_len + len + suf_len);
+      if (final != NULL)
+       {
+         memcpy (final, pre, pre_len);
+         memcpy (final + pre_len, res, len);
+         memcpy (final + pre_len + len, suf, suf_len);
+       }
+      free (res);
+      res = final;
+    }
+
+  return res;
+}