Automatic date update in version.in
[platform/upstream/binutils.git] / bfd / bfd.c
index 5ac3d9d..2d9397b 100644 (file)
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
-                          /* -*- C -*- */
+/* Generic BFD library interface and support routines.
+   Copyright (C) 1990-2014 Free Software Foundation, Inc.
+   Written by Cygnus Support.
 
-/*** bfd -- binary file diddling routines by Gumby Wallace of Cygnus Support.
-           Every definition in this file should be exported and declared
-           in bfd.h.  If you don't want it to be user-visible, put it in
-           libbfd.c!
-*/
-
-/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+   This file is part of BFD, the Binary File Descriptor library.
 
-This file is part of BFD, the Binary File Diddler.
+   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.
 
-BFD 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 1, 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.
 
-BFD 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.  */
 
-You should have received a copy of the GNU General Public License
-along with BFD; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+/*
+INODE
+typedef bfd, Error reporting, BFD front end, BFD front end
+
+SECTION
+       <<typedef bfd>>
+
+       A BFD has type <<bfd>>; objects of this type are the
+       cornerstone of any application using BFD. Using BFD
+       consists of making references though the BFD and to data in the BFD.
+
+       Here is the structure that defines the type <<bfd>>.  It
+       contains the major data about the file and pointers
+       to the rest of the data.
+
+CODE_FRAGMENT
+.
+.enum bfd_direction
+.  {
+.    no_direction = 0,
+.    read_direction = 1,
+.    write_direction = 2,
+.    both_direction = 3
+.  };
+.
+.struct bfd
+.{
+.  {* The filename the application opened the BFD with.  *}
+.  const char *filename;
+.
+.  {* A pointer to the target jump table.  *}
+.  const struct bfd_target *xvec;
+.
+.  {* The IOSTREAM, and corresponding IO vector that provide access
+.     to the file backing the BFD.  *}
+.  void *iostream;
+.  const struct bfd_iovec *iovec;
+.
+.  {* The caching routines use these to maintain a
+.     least-recently-used list of BFDs.  *}
+.  struct bfd *lru_prev, *lru_next;
+.
+.  {* When a file is closed by the caching routines, BFD retains
+.     state information on the file here...  *}
+.  ufile_ptr where;
+.
+.  {* File modified time, if mtime_set is TRUE.  *}
+.  long mtime;
+.
+.  {* A unique identifier of the BFD  *}
+.  unsigned int id;
+.
+.  {* The format which belongs to the BFD. (object, core, etc.)  *}
+.  ENUM_BITFIELD (bfd_format) format : 3;
+.
+.  {* The direction with which the BFD was opened.  *}
+.  ENUM_BITFIELD (bfd_direction) direction : 2;
+.
+.  {* Format_specific flags.  *}
+.  flagword flags : 17;
+.
+.  {* 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
+.
+.  {* This BFD has been created by the linker and doesn't correspond
+.     to any input file.  *}
+.#define BFD_LINKER_CREATED 0x1000
+.
+.  {* 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 0x2000
+.
+.  {* Compress sections in this BFD.  *}
+.#define BFD_COMPRESS 0x4000
+.
+.  {* Decompress sections in this BFD.  *}
+.#define BFD_DECOMPRESS 0x8000
+.
+.  {* BFD is a dummy, for plugins.  *}
+.#define BFD_PLUGIN 0x10000
+.
+.  {* Flags bits to be saved in bfd_preserve_save.  *}
+.#define BFD_FLAGS_SAVED \
+.  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_PLUGIN)
+.
+.  {* Flags bits which are for BFD use only.  *}
+.#define BFD_FLAGS_FOR_BFD_USE_MASK \
+.  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
+.   | BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT)
+.
+.  {* 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;
+.
+.  {* Set if only required symbols should be added in the link hash table for
+.     this object.  Used by VMS linkers.  *}
+.  unsigned int selective_search : 1;
+.
+.  {* Set if this is the linker output BFD.  *}
+.  unsigned int is_linker_output : 1;
+.
+.  {* 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;
+.
+.  {* 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;
+.
+.  {* Pointer to linked list of sections.  *}
+.  struct bfd_section *sections;
+.
+.  {* The last section on the section list.  *}
+.  struct bfd_section *section_last;
+.
+.  {* The number of sections.  *}
+.  unsigned int section_count;
+.
+.  {* A field used by _bfd_generic_link_add_archive_symbols.  This will
+.     be used only for archive elements.  *}
+.  int archive_pass;
+.
+.  {* Stuff only useful for object files:
+.     The start address.  *}
+.  bfd_vma start_address;
+.
+.  {* Symbol table for output BFD (with symcount entries).
+.     Also used by the linker to cache input BFD symbols.  *}
+.  struct bfd_symbol  **outsymbols;
+.
+.  {* Used for input and output.  *}
+.  unsigned int symcount;
+.
+.  {* Used for slurped dynamic symbol tables.  *}
+.  unsigned int dynsymcount;
+.
+.  {* Pointer to structure which contains architecture information.  *}
+.  const struct bfd_arch_info *arch_info;
+.
+.  {* Stuff only useful for archives.  *}
+.  void *arelt_data;
+.  struct bfd *my_archive;      {* The containing archive BFD.  *}
+.  struct bfd *archive_next;    {* The next BFD in the archive.  *}
+.  struct bfd *archive_head;    {* The first BFD in the archive.  *}
+.  struct bfd *nested_archives; {* List of nested archive in a flattened
+.                                  thin archive.  *}
+.
+.  union {
+.    {* For input BFDs, a chain of BFDs involved in a link.  *}
+.    struct bfd *next;
+.    {* For output BFD, the linker hash table.  *}
+.    struct bfd_link_hash_table *hash;
+.  } link;
+.
+.  {* Used by the back end to hold private data.  *}
+.  union
+.    {
+.      struct aout_data_struct *aout_data;
+.      struct artdata *aout_ar_data;
+.      struct _oasys_data *oasys_obj_data;
+.      struct _oasys_ar_data *oasys_ar_data;
+.      struct coff_tdata *coff_obj_data;
+.      struct pe_tdata *pe_obj_data;
+.      struct xcoff_tdata *xcoff_obj_data;
+.      struct ecoff_tdata *ecoff_obj_data;
+.      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;
+.      struct nlm_obj_tdata *nlm_obj_data;
+.      struct bout_data_struct *bout_data;
+.      struct mmo_data_struct *mmo_data;
+.      struct sun_core_struct *sun_core_data;
+.      struct sco5_core_struct *sco5_core_data;
+.      struct trad_core_struct *trad_core_data;
+.      struct som_data_struct *som_data;
+.      struct hpux_core_struct *hpux_core_data;
+.      struct hppabsd_core_struct *hppabsd_core_data;
+.      struct sgi_core_struct *sgi_core_data;
+.      struct lynx_core_struct *lynx_core_data;
+.      struct osf_core_struct *osf_core_data;
+.      struct cisco_core_struct *cisco_core_data;
+.      struct versados_data_struct *versados_data;
+.      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;
+.      void *any;
+.    }
+.  tdata;
+.
+.  {* Used by the application to hold private data.  *}
+.  void *usrdata;
+.
+.  {* Where all the allocated stuff under this BFD goes.  This is a
+.     struct objalloc *, but we use void * to avoid requiring the inclusion
+.     of objalloc.h.  *}
+.  void *memory;
+.};
+.
+.{* See note beside bfd_set_section_userdata.  *}
+.static inline bfd_boolean
+.bfd_set_cacheable (bfd * abfd, bfd_boolean val)
+.{
+.  abfd->cacheable = val;
+.  return TRUE;
+.}
+.
+*/
 
-/* $Id$ */
-#include <sysdep.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"
+#include "coff/internal.h"
+#include "coff/sym.h"
+#include "libcoff.h"
+#include "libecoff.h"
+#undef obj_symbols
+#include "elf-bfd.h"
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
 
-short _bfd_host_big_endian = 0x0100;
-       /* Accessing the above as (*(char*)&_bfd_host_big_endian), will
-          return 1 if the host is big-endian, 0 otherwise.
-          (assuming that a short is two bytes long!!!  FIXME)
-          (See HOST_IS_BIG_ENDIAN_P in bfd.h.)  */
 \f
-/** Error handling
-    o - Most functions return nonzero on success (check doc for
-       precise semantics); 0 or NULL on error.
-    o - Internal errors are documented by the value of bfd_error.
-       If that is system_call_error then check errno.
-    o - The easiest way to report this to the user is to use bfd_perror.
-*/
-
-bfd_ec bfd_error = no_error;
-
-char *bfd_errmsgs[] = {        "No error",
-                       "System call error",
-                       "Invalid target",
-                       "File in wrong format",
-                       "Invalid operation",
-                       "Memory exhausted",
-                       "No symbols",
-                       "No relocation info",
-                       "No more archived files",
-                       "Malformed archive",
-                       "Symbol not found",
-                       "File format not recognized",
-                       "File format is ambiguous",
-                       "Section has no contents",
-                       "Nonrepresentable section on output",
-                       "#<Invalid error code>"
-                      };
-
-static 
-void 
-DEFUN(bfd_nonrepresentable_section,(abfd, name),
-        CONST  bfd * CONST abfd AND
-        CONST  char * CONST name)
-{
-  printf("bfd error writing file %s, format %s can't represent section %s\n",
-        abfd->filename, 
-        abfd->xvec->name,
-        name);
-  exit(1);
-}
-
-bfd_error_vector_type bfd_error_vector = 
-  {
-  bfd_nonrepresentable_section 
-  };
-
-#if 1 || !defined(ANSI_LIBRARIES) && !defined(__STDC__)
-char *
-strerror (code)
-     int code;
+/* provide storage for subsystem, stack and heap data which may have been
+   passed in on the command line.  Ld puts this data into a bfd_link_info
+   struct which ultimately gets passed in to the bfd.  When it arrives, copy
+   it to the following struct so that the data will be available in coffcode.h
+   where it is needed.  The typedef's used are defined in bfd.h */
+\f
+/*
+INODE
+Error reporting, Miscellaneous, typedef bfd, BFD front end
+
+SECTION
+       Error reporting
+
+       Most BFD functions return nonzero on success (check their
+       individual documentation for precise semantics).  On an error,
+       they call <<bfd_set_error>> to set an error condition that callers
+       can check by calling <<bfd_get_error>>.
+        If that returns <<bfd_error_system_call>>, then check
+       <<errno>>.
+
+       The easiest way to report a BFD error to the user is to
+       use <<bfd_perror>>.
+
+SUBSECTION
+       Type <<bfd_error_type>>
+
+       The values returned by <<bfd_get_error>> are defined by the
+       enumerated type <<bfd_error_type>>.
+
+CODE_FRAGMENT
+.
+.typedef enum bfd_error
+.{
+.  bfd_error_no_error = 0,
+.  bfd_error_system_call,
+.  bfd_error_invalid_target,
+.  bfd_error_wrong_format,
+.  bfd_error_wrong_object_format,
+.  bfd_error_invalid_operation,
+.  bfd_error_no_memory,
+.  bfd_error_no_symbols,
+.  bfd_error_no_armap,
+.  bfd_error_no_more_archived_files,
+.  bfd_error_malformed_archive,
+.  bfd_error_missing_dso,
+.  bfd_error_file_not_recognized,
+.  bfd_error_file_ambiguously_recognized,
+.  bfd_error_no_contents,
+.  bfd_error_nonrepresentable_section,
+.  bfd_error_no_debug_section,
+.  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;
+.
+*/
+
+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[] =
 {
-  extern int sys_nerr;
-  extern char *sys_errlist[];
+  N_("No error"),
+  N_("System call error"),
+  N_("Invalid bfd target"),
+  N_("File in wrong format"),
+  N_("Archive object file in wrong format"),
+  N_("Invalid operation"),
+  N_("Memory exhausted"),
+  N_("No symbols"),
+  N_("Archive has no index; run ranlib to add one"),
+  N_("No more archived files"),
+  N_("Malformed archive"),
+  N_("DSO missing from command line"),
+  N_("File format not recognized"),
+  N_("File format is ambiguous"),
+  N_("Section has no contents"),
+  N_("Nonrepresentable section on output"),
+  N_("Symbol needs debug section which does not exist"),
+  N_("Bad value"),
+  N_("File truncated"),
+  N_("File too big"),
+  N_("Error reading %s: %s"),
+  N_("#<Invalid error code>")
+};
 
-  return (((code < 0) || (code >= sys_nerr)) ? "(unknown error)" :
-         sys_errlist [code]);
+/*
+FUNCTION
+       bfd_get_error
+
+SYNOPSIS
+       bfd_error_type bfd_get_error (void);
+
+DESCRIPTION
+       Return the current BFD error condition.
+*/
+
+bfd_error_type
+bfd_get_error (void)
+{
+  return bfd_error;
 }
-#endif /* not ANSI_LIBRARIES */
 
+/*
+FUNCTION
+       bfd_set_error
 
-char *
-bfd_errmsg (error_tag)
-     bfd_ec error_tag;
+SYNOPSIS
+       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_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);
+    }
+}
+
+/*
+FUNCTION
+       bfd_errmsg
+
+SYNOPSIS
+       const char *bfd_errmsg (bfd_error_type error_tag);
+
+DESCRIPTION
+       Return a string describing the error @var{error_tag}, or
+       the system error if @var{error_tag} is <<bfd_error_system_call>>.
+*/
+
+const char *
+bfd_errmsg (bfd_error_type error_tag)
 {
 #ifndef errno
   extern int errno;
 #endif
-  if (error_tag == system_call_error)
-    return strerror (errno);
+  if (error_tag == bfd_error_on_input)
+    {
+      char *buf;
+      const char *msg = bfd_errmsg (input_error);
 
-  if ((((int)error_tag <(int) no_error) ||
-       ((int)error_tag > (int)invalid_error_code)))
-    error_tag = invalid_error_code;/* sanity check */
+      if (asprintf (&buf, _(bfd_errmsgs [error_tag]), input_bfd->filename, msg)
+         != -1)
+       return buf;
 
-  return bfd_errmsgs [(int)error_tag];
+      /* Ick, what to do on out of memory?  */
+      return msg;
+    }
+
+  if (error_tag == bfd_error_system_call)
+    return xstrerror (errno);
+
+  if (error_tag > bfd_error_invalid_error_code)
+    error_tag = bfd_error_invalid_error_code;  /* sanity check */
+
+  return _(bfd_errmsgs [error_tag]);
 }
 
+/*
+FUNCTION
+       bfd_perror
+
+SYNOPSIS
+       void bfd_perror (const char *message);
+
+DESCRIPTION
+       Print to the standard error stream a string describing the
+       last BFD error that occurred, or the last system error if
+       the last BFD error was a system call failure.  If @var{message}
+       is non-NULL and non-empty, the error string printed is preceded
+       by @var{message}, a colon, and a space.  It is followed by a newline.
+*/
 
-void bfd_default_error_trap(error_tag)
-bfd_ec error_tag;
+void
+bfd_perror (const char *message)
 {
-  printf("bfd assert fail (%s)\n", bfd_errmsg(error_tag));
+  fflush (stdout);
+  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 ()));
+  fflush (stderr);
 }
 
-void (*bfd_error_trap)() = bfd_default_error_trap;
-void (*bfd_error_nonrepresentabltrap)() = bfd_default_error_trap;
+/*
+SUBSECTION
+       BFD error handler
+
+       Some BFD functions want to print messages describing the
+       problem.  They call a BFD error handler function.  This
+       function may be overridden by the program.
+
+       The BFD error handler acts like printf.
+
+CODE_FRAGMENT
+.
+.typedef void (*bfd_error_handler_type) (const char *, ...);
+.
+*/
+
+/* The program name used when printing BFD error messages.  */
+
+static const char *_bfd_error_program_name;
+
+/* This is the default routine to handle BFD error messages.
+   Like fprintf (stderr, ...), but also handles some extra format specifiers.
+
+   %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
-DEFUN(bfd_perror,(message),
-      CONST char *message)
+_bfd_default_error_handler (const char *fmt, ...)
 {
-  if (bfd_error == system_call_error)
-    perror((char *)message);           /* must be system error then... */
-  else {
-    if (message == NULL || *message == '\0')
-      fprintf (stderr, "%s\n", bfd_errmsg (bfd_error));
-    else
-      fprintf (stderr, "%s: %s\n", message, bfd_errmsg (bfd_error));
-  }
-}
+  va_list ap;
+  char *bufp;
+  const char *new_fmt, *p;
+  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
+    fprintf (stderr, "BFD: ");
+
+  va_start (ap, fmt);
+  new_fmt = fmt;
+  bufp = buf;
+
+  /* Reserve enough space for the existing format string.  */
+  avail -= strlen (fmt) + 1;
+  if (avail > 1000)
+    _exit (EXIT_FAILURE);
+
+  p = fmt;
+  while (1)
+    {
+      char *q;
+      size_t len, extra, trim;
+
+      p = strchr (p, '%');
+      if (p == NULL || p[1] == '\0')
+       {
+         if (new_fmt == buf)
+           {
+             len = strlen (fmt);
+             memcpy (bufp, fmt, len + 1);
+           }
+         break;
+       }
 
-/* for error messages */
-char *
-bfd_format_string (format)
-     bfd_format format;
-{
-  if (((int)format <(int) bfd_unknown) || ((int)format >=(int) bfd_type_end)) return "invalid";
-  
-  switch (format) {
-  case bfd_object: return "object"; /* linker/assember/compiler output */
-  case bfd_archive: return "archive"; /* object archive file */
-  case bfd_core: return "core";        /* core dump */
-  default: return "unknown";
-  }
+      if (p[1] == 'A' || p[1] == 'B')
+       {
+         len = p - fmt;
+         memcpy (bufp, fmt, len);
+         bufp += len;
+         fmt = p + 2;
+         new_fmt = buf;
+
+         /* If we run out of space, tough, you lose your ridiculously
+            long file or section name.  It's not safe to try to alloc
+            memory here;  We might be printing an out of memory message.  */
+         if (avail == 0)
+           {
+             *bufp++ = '*';
+             *bufp++ = '*';
+             *bufp = '\0';
+           }
+         else
+           {
+             if (p[1] == 'B')
+               {
+                 bfd *abfd = va_arg (ap, bfd *);
+
+                 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
+                   snprintf (bufp, avail, "%s", abfd->filename);
+               }
+             else
+               {
+                 asection *sec = va_arg (ap, asection *);
+                 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
+                     && (sec->flags & SEC_GROUP) == 0)
+                   group = elf_group_name (sec);
+                 else if (abfd != NULL
+                          && bfd_get_flavour (abfd) == bfd_target_coff_flavour
+                          && (ci = bfd_coff_get_comdat_section (sec->owner,
+                                                                sec)) != NULL)
+                   group = ci->name;
+                 if (group != NULL)
+                   snprintf (bufp, avail, "%s[%s]", sec->name, group);
+                 else
+                   snprintf (bufp, avail, "%s", sec->name);
+               }
+             len = strlen (bufp);
+             avail = avail - len + 2;
+
+             /* We need to replace any '%' we printed by "%%".
+                First count how many.  */
+             q = bufp;
+             bufp += len;
+             extra = 0;
+             while ((q = strchr (q, '%')) != NULL)
+               {
+                 ++q;
+                 ++extra;
+               }
+
+             /* If there isn't room, trim off the end of the string.  */
+             q = bufp;
+             bufp += extra;
+             if (extra > avail)
+               {
+                 trim = extra - avail;
+                 bufp -= trim;
+                 do
+                   {
+                     if (*--q == '%')
+                       --extra;
+                   }
+                 while (--trim != 0);
+                 *q = '\0';
+                 avail = extra;
+               }
+             avail -= extra;
+
+             /* Now double all '%' chars, shuffling the string as we go.  */
+             while (extra != 0)
+               {
+                 while ((q[extra] = *q) != '%')
+                   --q;
+                 q[--extra] = '%';
+                 --q;
+               }
+           }
+       }
+      p = p + 2;
+    }
+
+  vfprintf (stderr, new_fmt, ap);
+  va_end (ap);
+
+  /* On AIX, putc is implemented as a macro that triggers a -Wunused-value
+     warning, so use the fputc function to avoid it.  */
+  fputc ('\n', stderr);
+  fflush (stderr);
 }
-\f
-/** Target configurations */
 
-extern bfd_target *target_vector[];
+/* This is a function pointer to the routine which should handle BFD
+   error messages.  It is called when a BFD routine encounters an
+   error for which it wants to print a message.  Going through a
+   function pointer permits a program linked against BFD to intercept
+   the messages and deal with them itself.  */
 
-/* Returns a pointer to the transfer vector for the object target
-   named target_name.  If target_name is NULL, chooses the one in the
-   environment variable GNUTARGET; if that is null or not defined then
-   the first entry in the target list is chosen.  Passing in the
-   string "default" or setting the environment variable to "default"
-   will cause the first entry in the target list to be returned. */
+bfd_error_handler_type _bfd_error_handler = _bfd_default_error_handler;
 
-bfd_target *
-DEFUN(bfd_find_target,(target_name),
-      CONST char *target_name)
-{
-  bfd_target **target;
-  extern char *getenv ();
-  CONST char *targname = (target_name ? target_name : getenv ("GNUTARGET"));
+/*
+FUNCTION
+       bfd_set_error_handler
 
-  /* This is safe; the vector cannot be null */
-  if (targname == NULL || !strcmp (targname, "default"))
-    return target_vector[0];
+SYNOPSIS
+       bfd_error_handler_type bfd_set_error_handler (bfd_error_handler_type);
 
-  for (target = &target_vector[0]; *target != NULL; target++) {
-    if (!strcmp (targname, (*target)->name))
-      return *target;
-  }
+DESCRIPTION
+       Set the BFD error handler function.  Returns the previous
+       function.
+*/
+
+bfd_error_handler_type
+bfd_set_error_handler (bfd_error_handler_type pnew)
+{
+  bfd_error_handler_type pold;
 
-  bfd_error = invalid_target;
-  return NULL;
+  pold = _bfd_error_handler;
+  _bfd_error_handler = pnew;
+  return pold;
 }
 
-/* Returns a freshly-consed, NULL-terminated vector of the names of all the
-   valid bfd targets.  Do not modify the names */
+/*
+FUNCTION
+       bfd_set_error_program_name
+
+SYNOPSIS
+       void bfd_set_error_program_name (const char *);
 
-char **
-bfd_target_list ()
+DESCRIPTION
+       Set the program name to use when printing a BFD error.  This
+       is printed before the error message followed by a colon and
+       space.  The string must not be changed after it is passed to
+       this function.
+*/
+
+void
+bfd_set_error_program_name (const char *name)
 {
-  int vec_length= 0;
-  bfd_target **target;
-  char **name_list, **name_ptr;
+  _bfd_error_program_name = name;
+}
+
+/*
+FUNCTION
+       bfd_get_error_handler
+
+SYNOPSIS
+       bfd_error_handler_type bfd_get_error_handler (void);
+
+DESCRIPTION
+       Return the BFD error handler function.
+*/
 
-  for (target = &target_vector[0]; *target != NULL; target++)
-    vec_length++;
+bfd_error_handler_type
+bfd_get_error_handler (void)
+{
+  return _bfd_error_handler;
+}
 
-  name_ptr = name_list = (char **) zalloc ((vec_length + 1) * sizeof (char **));
+/*
+SUBSECTION
+       BFD assert handler
+
+       If BFD finds an internal inconsistency, the bfd assert
+       handler is called with information on the BFD version, BFD
+       source file and line.  If this happens, most programs linked
+       against BFD are expected to want to exit with an error, or mark
+       the current BFD operation as failed, so it is recommended to
+       override the default handler, which just calls
+       _bfd_error_handler and continues.
+
+CODE_FRAGMENT
+.
+.typedef void (*bfd_assert_handler_type) (const char *bfd_formatmsg,
+.                                         const char *bfd_version,
+.                                         const char *bfd_file,
+.                                         int bfd_line);
+.
+*/
 
-  if (name_list == NULL) {
-    bfd_error = no_memory;
-    return NULL;
-  }
+/* Note the use of bfd_ prefix on the parameter names above: we want to
+   show which one is the message and which is the version by naming the
+   parameters, but avoid polluting the program-using-bfd namespace as
+   the typedef is visible in the exported headers that the program
+   includes.  Below, it's just for consistency.  */
 
-  for (target = &target_vector[0]; *target != NULL; target++)
-    *(name_ptr++) = (*target)->name;
+static void
+_bfd_default_assert_handler (const char *bfd_formatmsg,
+                            const char *bfd_version,
+                            const char *bfd_file,
+                            int bfd_line)
 
-  return name_list;
+{
+  (*_bfd_error_handler) (bfd_formatmsg, bfd_version, bfd_file, bfd_line);
 }
 
-/** Init a bfd for read of the proper format.
- */
+/* Similar to _bfd_error_handler, a program can decide to exit on an
+   internal BFD error.  We use a non-variadic type to simplify passing
+   on parameters to other functions, e.g. _bfd_error_handler.  */
 
-/* We should be able to find out if the target was defaulted or user-specified.
-   If the user specified the target explicitly then we should do no search.
-   I guess the best way to do this is to pass an extra argument which specifies
-   the DWIM. */
-
-/* I have chanegd this always to set the filepos to the origin before
-   guessing.  -- Gumby, 14 Februar 1991*/
-
-boolean
-DEFUN(bfd_check_format,(abfd, format),
-      bfd *abfd AND
-      bfd_format format)
-{
-  bfd_target **target, *save_targ, *right_targ;
-  int match_count;
-
-  if (!bfd_read_p (abfd) ||
-      ((int)(abfd->format) < (int)bfd_unknown) ||
-      ((int)(abfd->format) >= (int)bfd_type_end)) {
-    bfd_error = invalid_operation;
-    return false;
-  }
-
-  if (abfd->format != bfd_unknown) return (abfd->format == format) ? true:false;
-
-  /* presume the answer is yes */
-  abfd->format = format;
-
-  bfd_seek (abfd, (file_ptr)0, SEEK_SET);      /* rewind! */
-
-  right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
-  if (right_targ) {
-    abfd->xvec = right_targ;           /* Set the target as returned */
-    return true;                       /* File position has moved, BTW */
-  }
-
-  /* This isn't a <format> file in the specified or defaulted target type.
-     See if we recognize it for any other target type.  (We check them
-     all to make sure it's uniquely recognized.)  */
-
-  save_targ = abfd->xvec;
-  match_count = 0;
-  right_targ = 0;
-
-  for (target = target_vector; *target != NULL; target++) {
-    bfd_target *temp;
-
-    abfd->xvec = *target;      /* Change BFD's target temporarily */
-    bfd_seek (abfd, (file_ptr)0, SEEK_SET);
-    temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
-    if (temp) {                                /* This format checks out as ok! */
-      right_targ = temp;
-      match_count++;
-#ifdef GNU960
-      /* Big- and little-endian b.out archives look the same, but it doesn't
-       * matter: there is no difference in their headers, and member file byte
-       * orders will (I hope) be handled appropriately by bfd.  Ditto for big
-       * and little coff archives.  And the 4 coff/b.out object formats are
-       * unambiguous.  So accept the first match we find.
-       */
-      break;
-#endif
-    }
-  }
-
-  if (match_count == 1) {
-    abfd->xvec = right_targ;           /* Change BFD's target permanently */
-    return true;                       /* File position has moved, BTW */
-  }
-
-  abfd->xvec = save_targ;              /* Restore original target type */
-  abfd->format = bfd_unknown;          /* Restore original format */
-  bfd_error = ((match_count == 0) ? file_not_recognized :
-              file_ambiguously_recognized);
-  return false;
-    }
+bfd_assert_handler_type _bfd_assert_handler = _bfd_default_assert_handler;
+
+/*
+FUNCTION
+       bfd_set_assert_handler
+
+SYNOPSIS
+       bfd_assert_handler_type bfd_set_assert_handler (bfd_assert_handler_type);
+
+DESCRIPTION
+       Set the BFD assert handler function.  Returns the previous
+       function.
+*/
 
-boolean
-DEFUN(bfd_set_format,(abfd, format),
-      bfd *abfd AND
-      bfd_format format)
+bfd_assert_handler_type
+bfd_set_assert_handler (bfd_assert_handler_type pnew)
 {
+  bfd_assert_handler_type pold;
 
-  if (bfd_read_p (abfd) ||
-      ((int)abfd->format < (int)bfd_unknown) ||
-      ((int)abfd->format >= (int)bfd_type_end)) {
-    bfd_error = invalid_operation;
-    return false;
-  }
+  pold = _bfd_assert_handler;
+  _bfd_assert_handler = pnew;
+  return pold;
+}
 
-  if (abfd->format != bfd_unknown) return (abfd->format == format) ? true:false;
+/*
+FUNCTION
+       bfd_get_assert_handler
 
-  /* presume the answer is yes */
-  abfd->format = format;
+SYNOPSIS
+       bfd_assert_handler_type bfd_get_assert_handler (void);
 
-  if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd))) {
-    abfd->format = bfd_unknown;
-    return false;
-  }
+DESCRIPTION
+       Return the BFD assert handler function.
+*/
 
-  return true;
+bfd_assert_handler_type
+bfd_get_assert_handler (void)
+{
+  return _bfd_assert_handler;
 }
 \f
-/* Hack object and core file sections */
-
-sec_ptr
-DEFUN(bfd_get_section_by_name,(abfd, name),
-      bfd *abfd AND
-      CONST char *name)
-{
-  asection *sect;
-  
-  for (sect = abfd->sections; sect != NULL; sect = sect->next)
-    if (!strcmp (sect->name, name)) return sect;
-  return NULL;
-}
-
-/* If you try to create a section with a name which is already in use,
-   returns the old section by that name instead. */
-sec_ptr
-DEFUN(bfd_make_section,(abfd, name),
-      bfd *abfd AND
-      CONST char *CONST name)
-{
-  asection *newsect;  
-  asection **  prev = &abfd->sections;
-  asection * sect = abfd->sections;
-  
-  if (abfd->output_has_begun) {
-    bfd_error = invalid_operation;
-    return NULL;
-  }
-
-  while (sect) {
-    if (!strcmp(sect->name, name)) return sect;
-    prev = &sect->next;
-    sect = sect->next;
-  }
-
-  newsect = (asection *) bfd_zalloc(abfd, sizeof (asection));
-  if (newsect == NULL) {
-    bfd_error = no_memory;
-    return NULL;
-  }
-
-  newsect->name = name;
-  newsect->index = abfd->section_count++;
-  newsect->flags = SEC_NO_FLAGS;
-
-  newsect->userdata = 0;
-  newsect->next = (asection *)NULL;
-  newsect->relocation = (arelent *)NULL;
-  newsect->reloc_count = 0;
-  newsect->line_filepos =0;
-
-  if (BFD_SEND (abfd, _new_section_hook, (abfd, newsect)) != true) {
-    free (newsect);
-    return NULL;
-  }
-
-  *prev = newsect;
-  return newsect;
-}
-
-/* Call operation on each section.  Operation gets three args: the bfd,
-   the section, and a void * pointer (whatever the user supplied). */
-
-/* This is attractive except that without lexical closures its use is hard
-   to make reentrant. */
-/*VARARGS2*/
-void
-bfd_map_over_sections (abfd, operation, user_storage)
-     bfd *abfd;
-     void (*operation)();
-     PTR user_storage;
+/*
+INODE
+Miscellaneous, Memory Usage, Error reporting, BFD front end
+
+SECTION
+       Miscellaneous
+
+SUBSECTION
+       Miscellaneous functions
+*/
+
+/*
+FUNCTION
+       bfd_get_reloc_upper_bound
+
+SYNOPSIS
+       long bfd_get_reloc_upper_bound (bfd *abfd, asection *sect);
+
+DESCRIPTION
+       Return the number of bytes required to store the
+       relocation information associated with section @var{sect}
+       attached to bfd @var{abfd}.  If an error occurs, return -1.
+
+*/
+
+long
+bfd_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
 {
-  asection *sect;
-  int i = 0;
-  
-  for (sect = abfd->sections; sect != NULL; i++, sect = sect->next)
-    (*operation) (abfd, sect, user_storage);
+  if (abfd->format != bfd_object)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return -1;
+    }
 
-  if (i != abfd->section_count)                /* Debugging */
-    abort();
+  return BFD_SEND (abfd, _get_reloc_upper_bound, (abfd, asect));
 }
 
-boolean
-bfd_set_section_flags (abfd, section, flags)
-     bfd *abfd;
-     sec_ptr section;
-     flagword flags;
+/*
+FUNCTION
+       bfd_canonicalize_reloc
+
+SYNOPSIS
+       long bfd_canonicalize_reloc
+         (bfd *abfd, asection *sec, arelent **loc, asymbol **syms);
+
+DESCRIPTION
+       Call the back end associated with the open BFD
+       @var{abfd} and translate the external form of the relocation
+       information attached to @var{sec} into the internal canonical
+       form.  Place the table into memory at @var{loc}, which has
+       been preallocated, usually by a call to
+       <<bfd_get_reloc_upper_bound>>.  Returns the number of relocs, or
+       -1 on error.
+
+       The @var{syms} table is also needed for horrible internal magic
+       reasons.
+
+*/
+long
+bfd_canonicalize_reloc (bfd *abfd,
+                       sec_ptr asect,
+                       arelent **location,
+                       asymbol **symbols)
 {
-  if ((flags & bfd_applicable_section_flags (abfd)) != flags) {
-    bfd_error = invalid_operation;
-    return false;
-  }
+  if (abfd->format != bfd_object)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return -1;
+    }
 
-   section->flags = flags;
-return true;
+  return BFD_SEND (abfd, _bfd_canonicalize_reloc,
+                  (abfd, asect, location, symbols));
 }
 
+/*
+FUNCTION
+       bfd_set_reloc
 
-boolean
-bfd_set_section_size (abfd, ptr, val)
-     bfd *abfd;
-     sec_ptr ptr;
-     unsigned long val;
-{
-  /* Once you've started writing to any section you cannot create or change
-     the size of any others. */
+SYNOPSIS
+       void bfd_set_reloc
+         (bfd *abfd, asection *sec, arelent **rel, unsigned int count);
+
+DESCRIPTION
+       Set the relocation pointer and count within
+       section @var{sec} to the values @var{rel} and @var{count}.
+       The argument @var{abfd} is ignored.
 
-  if (abfd->output_has_begun) {
-    bfd_error = invalid_operation;
-    return false;
-  }
+*/
 
-  ptr->size = val;
-  
-  return true;
+void
+bfd_set_reloc (bfd *ignore_abfd ATTRIBUTE_UNUSED,
+              sec_ptr asect,
+              arelent **location,
+              unsigned int count)
+{
+  asect->orelocation = location;
+  asect->reloc_count = count;
 }
 
-boolean
-DEFUN(bfd_set_section_contents,(abfd, section, location, offset, count),
-      bfd *abfd AND
-      sec_ptr section AND
-      PTR location AND
-      file_ptr offset AND
-      bfd_size_type count)
+/*
+FUNCTION
+       bfd_set_file_flags
+
+SYNOPSIS
+       bfd_boolean bfd_set_file_flags (bfd *abfd, flagword flags);
+
+DESCRIPTION
+       Set the flag word in the BFD @var{abfd} to the value @var{flags}.
+
+       Possible errors are:
+       o <<bfd_error_wrong_format>> - The target bfd was not of object format.
+       o <<bfd_error_invalid_operation>> - The target bfd was open for reading.
+       o <<bfd_error_invalid_operation>> -
+       The flag word contained a bit which was not applicable to the
+       type of file.  E.g., an attempt was made to set the <<D_PAGED>> bit
+       on a BFD format which does not support demand paging.
+
+*/
+
+bfd_boolean
+bfd_set_file_flags (bfd *abfd, flagword flags)
 {
-       if (!(bfd_get_section_flags(abfd, section) &
-             SEC_HAS_CONTENTS)) {
-               bfd_error = no_contents;
-               return(false);
-       } /* if section has no contents */
+  if (abfd->format != bfd_object)
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return FALSE;
+    }
+
+  if (bfd_read_p (abfd))
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return FALSE;
+    }
 
-  if (BFD_SEND (abfd, _bfd_set_section_contents,
-           (abfd, section, location, offset, count))) {
-    abfd->output_has_begun = true;
-    return true;
-  }
+  bfd_get_file_flags (abfd) = flags;
+  if ((flags & bfd_applicable_file_flags (abfd)) != flags)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return FALSE;
+    }
 
-  return false;
+  return TRUE;
 }
 
-boolean
-DEFUN(bfd_get_section_contents,(abfd, section, location, offset, count),
-      bfd *abfd AND
-      sec_ptr section AND
-      PTR location AND
-      file_ptr offset AND
-      bfd_size_type count)
+void
+bfd_assert (const char *file, int line)
 {
-  if (section->flags & SEC_CONSTRUCTOR) {
-    memset(location, 0, (unsigned)count);
-    return true;
-  }
-  else {
-    return  (BFD_SEND (abfd, _bfd_get_section_contents,
-                      (abfd, section, location, offset, count)));
-  }
+  (*_bfd_assert_handler) (_("BFD %s assertion fail %s:%d"),
+                         BFD_VERSION_STRING, file, line);
 }
 
-\f
-/** Some core file info commands */
-
-/* Returns a read-only string explaining what program was running when
-   it failed. */
+/* A more or less friendly abort message.  In libbfd.h abort is
+   defined to call this function.  */
 
-char *
-bfd_core_file_failing_command (abfd)
-     bfd *abfd;
+void
+_bfd_abort (const char *file, int line, const char *fn)
 {
-  if (abfd->format != bfd_core) {
-    bfd_error = invalid_operation;
-    return NULL;
-  }
-  return BFD_SEND (abfd, _core_file_failing_command, (abfd));
+  if (fn != NULL)
+    (*_bfd_error_handler)
+      (_("BFD %s internal error, aborting at %s line %d in %s\n"),
+       BFD_VERSION_STRING, file, line, fn);
+  else
+    (*_bfd_error_handler)
+      (_("BFD %s internal error, aborting at %s line %d\n"),
+       BFD_VERSION_STRING, file, line);
+  (*_bfd_error_handler) (_("Please report this bug.\n"));
+  _exit (EXIT_FAILURE);
 }
 
+/*
+FUNCTION
+       bfd_get_arch_size
+
+SYNOPSIS
+       int bfd_get_arch_size (bfd *abfd);
+
+DESCRIPTION
+       Returns the normalized architecture address size, in bits, as
+       determined by the object file's format.  By normalized, we mean
+       either 32 or 64.  For ELF, this information is included in the
+       header.  Use bfd_arch_bits_per_address for number of bits in
+       the architecture address.
+
+RETURNS
+       Returns the arch size in bits if known, <<-1>> otherwise.
+*/
+
 int
-bfd_core_file_failing_signal (abfd)
-     bfd *abfd;
+bfd_get_arch_size (bfd *abfd)
 {
-  if (abfd->format != bfd_core) {
-    bfd_error = invalid_operation;
-    return 0;
-  }
-  return BFD_SEND (abfd, _core_file_failing_signal, (abfd));
+  if (abfd->xvec->flavour == bfd_target_elf_flavour)
+    return get_elf_backend_data (abfd)->s->arch_size;
+
+  return bfd_arch_bits_per_address (abfd) > 32 ? 64 : 32;
 }
 
-boolean
-core_file_matches_executable_p (core_bfd, exec_bfd)
-     bfd *core_bfd, *exec_bfd;
+/*
+FUNCTION
+       bfd_get_sign_extend_vma
+
+SYNOPSIS
+       int bfd_get_sign_extend_vma (bfd *abfd);
+
+DESCRIPTION
+       Indicates if the target architecture "naturally" sign extends
+       an address.  Some architectures implicitly sign extend address
+       values when they are converted to types larger than the size
+       of an address.  For instance, bfd_get_start_address() will
+       return an address sign extended to fill a bfd_vma when this is
+       the case.
+
+RETURNS
+       Returns <<1>> if the target architecture is known to sign
+       extend addresses, <<0>> if the target architecture is known to
+       not sign extend addresses, and <<-1>> otherwise.
+*/
+
+int
+bfd_get_sign_extend_vma (bfd *abfd)
 {
-  if ((core_bfd->format != bfd_core) || (exec_bfd->format != bfd_object)) {
-    bfd_error = wrong_format;
-    return false;
-  }
+  char *name;
+
+  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+    return get_elf_backend_data (abfd)->sign_extend_vma;
+
+  name = bfd_get_target (abfd);
+
+  /* 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 (CONST_STRNEQ (name, "coff-go32")
+      || strcmp (name, "pe-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
+      || strcmp (name, "aixcoff-rs6000") == 0)
+    return 1;
+
+  if (CONST_STRNEQ (name, "mach-o"))
+    return 0;
 
-  return BFD_SEND (core_bfd, _core_file_matches_executable_p, (core_bfd, exec_bfd));
+  bfd_set_error (bfd_error_wrong_format);
+  return -1;
 }
-\f
-/** Symbols */
 
-boolean
-bfd_set_symtab (abfd, location, symcount)
-     bfd *abfd;
-     asymbol **location;
-     unsigned int symcount;
-{
-  if ((abfd->format != bfd_object) || (bfd_read_p (abfd))) {
-    bfd_error = invalid_operation;
-    return false;
-  }
+/*
+FUNCTION
+       bfd_set_start_address
+
+SYNOPSIS
+       bfd_boolean bfd_set_start_address (bfd *abfd, bfd_vma vma);
+
+DESCRIPTION
+       Make @var{vma} the entry point of output BFD @var{abfd}.
+
+RETURNS
+       Returns <<TRUE>> on success, <<FALSE>> otherwise.
+*/
 
-  bfd_get_outsymbols (abfd) = location;
-  bfd_get_symcount (abfd) = symcount;
-  return true;
+bfd_boolean
+bfd_set_start_address (bfd *abfd, bfd_vma vma)
+{
+  abfd->start_address = vma;
+  return TRUE;
 }
 
-/* returns the number of octets of storage required */
+/*
+FUNCTION
+       bfd_get_gp_size
+
+SYNOPSIS
+       unsigned int bfd_get_gp_size (bfd *abfd);
+
+DESCRIPTION
+       Return the maximum size of objects to be optimized using the GP
+       register under MIPS ECOFF.  This is typically set by the <<-G>>
+       argument to the compiler, assembler or linker.
+*/
+
 unsigned int
-get_reloc_upper_bound (abfd, asect)
-     bfd *abfd;
-     sec_ptr asect;
+bfd_get_gp_size (bfd *abfd)
 {
-  if (abfd->format != bfd_object) {
-    bfd_error = invalid_operation;
-    return 0;
-  }
-
-  return BFD_SEND (abfd, _get_reloc_upper_bound, (abfd, asect));
+  if (abfd->format == bfd_object)
+    {
+      if (abfd->xvec->flavour == bfd_target_ecoff_flavour)
+       return ecoff_data (abfd)->gp_size;
+      else if (abfd->xvec->flavour == bfd_target_elf_flavour)
+       return elf_gp_size (abfd);
+    }
+  return 0;
 }
 
-unsigned int
-bfd_canonicalize_reloc (abfd, asect, location, symbols)
-     bfd *abfd;
-     sec_ptr asect;
-     arelent **location;
-     asymbol **symbols;
-{
-  if (abfd->format != bfd_object) {
-    bfd_error = invalid_operation;
-    return 0;
-  }
+/*
+FUNCTION
+       bfd_set_gp_size
 
-  return BFD_SEND (abfd, _bfd_canonicalize_reloc, (abfd, asect, location, symbols));
-}
+SYNOPSIS
+       void bfd_set_gp_size (bfd *abfd, unsigned int i);
+
+DESCRIPTION
+       Set the maximum size of objects to be optimized using the GP
+       register under ECOFF or MIPS ELF.  This is typically set by
+       the <<-G>> argument to the compiler, assembler or linker.
+*/
 
 void
-bfd_print_symbol_vandf(file, symbol)
-PTR file;
-asymbol *symbol;
-{
-  flagword type = symbol->flags;
-  if (symbol->section != (asection *)NULL)
-      {
-
-       fprintf_vma(file, symbol->value+symbol->section->vma);
-      }
-  else 
-      {
-       fprintf_vma(file, symbol->value);
-      }
-  fprintf(file," %c%c%c%c%c%c%c",
-         (type & BSF_LOCAL)  ? 'l':' ',
-         (type & BSF_GLOBAL) ? 'g' : ' ',
-         (type & BSF_IMPORT) ? 'i' : ' ',
-         (type & BSF_EXPORT) ? 'e' : ' ',
-         (type & BSF_UNDEFINED) ? 'u' : ' ',
-         (type & BSF_FORT_COMM) ? 'c' : ' ',
-         (type & BSF_DEBUGGING) ? 'd' :' ');
-
-}
-
-
-boolean
-bfd_set_file_flags (abfd, flags)
-     bfd *abfd;
-     flagword flags;
-{
-  if (abfd->format != bfd_object) {
-    bfd_error = wrong_format;
-    return false;
-  }
-
-  if (bfd_read_p (abfd)) {
-    bfd_error = invalid_operation;
-    return false;
-  }
-
-  if ((flags & bfd_applicable_file_flags (abfd)) != flags) {
-    bfd_error = invalid_operation;
-    return false;
-  }
+bfd_set_gp_size (bfd *abfd, unsigned int i)
+{
+  /* Don't try to set GP size on an archive or core file!  */
+  if (abfd->format != bfd_object)
+    return;
+
+  if (abfd->xvec->flavour == bfd_target_ecoff_flavour)
+    ecoff_data (abfd)->gp_size = i;
+  else if (abfd->xvec->flavour == bfd_target_elf_flavour)
+    elf_gp_size (abfd) = i;
+}
 
-  bfd_get_file_flags (abfd) = flags;
-return true;
+/* Get the GP value.  This is an internal function used by some of the
+   relocation special_function routines on targets which support a GP
+   register.  */
+
+bfd_vma
+_bfd_get_gp_value (bfd *abfd)
+{
+  if (! abfd)
+    return 0;
+  if (abfd->format != bfd_object)
+    return 0;
+
+  if (abfd->xvec->flavour == bfd_target_ecoff_flavour)
+    return ecoff_data (abfd)->gp;
+  else if (abfd->xvec->flavour == bfd_target_elf_flavour)
+    return elf_gp (abfd);
+
+  return 0;
 }
 
+/* Set the GP value.  */
 
 void
-bfd_set_reloc (ignore_abfd, asect, location, count)
-     bfd *ignore_abfd;
-     sec_ptr asect;
-     arelent **location;
-     unsigned int count;
+_bfd_set_gp_value (bfd *abfd, bfd_vma v)
 {
-  asect->orelocation  = location;
-  asect->reloc_count = count;
+  if (! abfd)
+    abort ();
+  if (abfd->format != bfd_object)
+    return;
+
+  if (abfd->xvec->flavour == bfd_target_ecoff_flavour)
+    ecoff_data (abfd)->gp = v;
+  else if (abfd->xvec->flavour == bfd_target_elf_flavour)
+    elf_gp (abfd) = v;
 }
+
 /*
-If an output_bfd is supplied to this function the generated image
-will be relocatable, the relocations are copied to the output file
-after they have been changed to reflect the new state of the world.
-There are two ways of reflecting the results of partial linkage in an
-output file; by modifying the output data in place, and by modifying
-the relocation record. Some native formats (eg basic a.out and basic
-coff) have no way of specifying an addend in the relocation type, so
-the addend has to go in the output data.  This is no big deal since in
-these formats the output data slot will always be big enough for the
-addend. Complex reloc types with addends were invented to solve just
-this problem.
-*/
-
-bfd_reloc_status_enum_type
-DEFUN(bfd_perform_relocation,(abfd,
-                             reloc_entry,
-                             data,
-                             input_section,
-                             output_bfd),
-      bfd *abfd AND
-      arelent *reloc_entry AND
-      PTR data AND
-      asection *input_section AND
-      bfd *output_bfd)
-{
-  bfd_vma relocation;
-  bfd_reloc_status_enum_type flag = bfd_reloc_ok;
-  bfd_vma addr = reloc_entry->address ;
-  bfd_vma output_base = 0;
-  reloc_howto_type *howto = reloc_entry->howto;
-  asection *reloc_target_output_section;
-  asection *reloc_target_input_section;
-  asymbol *symbol;
-
-  if (reloc_entry->sym_ptr_ptr) {
-    symbol = *( reloc_entry->sym_ptr_ptr);
-    if ((symbol->flags & BSF_UNDEFINED) && output_bfd == (bfd *)NULL) {
-      flag = bfd_reloc_undefined;
-    }
-  }
-  else {
-    symbol = (asymbol*)NULL;
-  }
-
-  if (howto->special_function){
-    bfd_reloc_status_enum_type cont;
-    cont = howto->special_function(abfd,
-                                  reloc_entry,
-                                  symbol,
-                                  data,
-                                  input_section);
-    if (cont != bfd_reloc_continue) return cont;
-  }
-
-  /* 
-    Work out which section the relocation is targetted at and the
-    initial relocation command value.
-    */
-
-
-  if (symbol != (asymbol *)NULL){
-    if (symbol->flags & BSF_FORT_COMM) {
-      relocation = 0;
-    }
-    else {
-      relocation = symbol->value;
-    }
-    if (symbol->section != (asection *)NULL)
+FUNCTION
+       bfd_scan_vma
+
+SYNOPSIS
+       bfd_vma bfd_scan_vma (const char *string, const char **end, int base);
+
+DESCRIPTION
+       Convert, like <<strtoul>>, a numerical expression
+       @var{string} into a <<bfd_vma>> integer, and return that integer.
+       (Though without as many bells and whistles as <<strtoul>>.)
+       The expression is assumed to be unsigned (i.e., positive).
+       If given a @var{base}, it is used as the base for conversion.
+       A base of 0 causes the function to interpret the string
+       in hex if a leading "0x" or "0X" is found, otherwise
+       in octal if a leading zero is found, otherwise in decimal.
+
+       If the value would overflow, the maximum <<bfd_vma>> value is
+       returned.
+*/
+
+bfd_vma
+bfd_scan_vma (const char *string, const char **end, int base)
+{
+  bfd_vma value;
+  bfd_vma cutoff;
+  unsigned int cutlim;
+  int overflow;
+
+  /* Let the host do it if possible.  */
+  if (sizeof (bfd_vma) <= sizeof (unsigned long))
+    return strtoul (string, (char **) end, base);
+
+#ifdef HAVE_STRTOULL
+  if (sizeof (bfd_vma) <= sizeof (unsigned long long))
+    return strtoull (string, (char **) end, base);
+#endif
+
+  if (base == 0)
+    {
+      if (string[0] == '0')
        {
-         reloc_target_input_section = symbol->section;
+         if ((string[1] == 'x') || (string[1] == 'X'))
+           base = 16;
+         else
+           base = 8;
        }
-    else {
-      reloc_target_input_section = (asection *)NULL;
     }
-  }
-  else if (reloc_entry->section != (asection *)NULL)
-      {
-       relocation = 0;
-       reloc_target_input_section = reloc_entry->section;
-      }
-  else {
-    relocation = 0;
-    reloc_target_input_section = (asection *)NULL;
-  }
-
 
-  if (reloc_target_input_section != (asection *)NULL) {
+  if ((base < 2) || (base > 36))
+    base = 10;
 
-    reloc_target_output_section =
-      reloc_target_input_section->output_section;
+  if (base == 16
+      && string[0] == '0'
+      && (string[1] == 'x' || string[1] == 'X')
+      && ISXDIGIT (string[2]))
+    {
+      string += 2;
+    }
 
-    if (output_bfd && howto->partial_inplace==false) {
-      output_base = 0;
+  cutoff = (~ (bfd_vma) 0) / (bfd_vma) base;
+  cutlim = (~ (bfd_vma) 0) % (bfd_vma) base;
+  value = 0;
+  overflow = 0;
+  while (1)
+    {
+      unsigned int digit;
+
+      digit = *string;
+      if (ISDIGIT (digit))
+       digit = digit - '0';
+      else if (ISALPHA (digit))
+       digit = TOUPPER (digit) - 'A' + 10;
+      else
+       break;
+      if (digit >= (unsigned int) base)
+       break;
+      if (value > cutoff || (value == cutoff && digit > cutlim))
+       overflow = 1;
+      value = value * base + digit;
+      ++string;
     }
-    else {
-      output_base = reloc_target_output_section->vma;
 
+  if (overflow)
+    value = ~ (bfd_vma) 0;
+
+  if (end != NULL)
+    *end = string;
+
+  return value;
+}
+
+/*
+FUNCTION
+       bfd_copy_private_header_data
+
+SYNOPSIS
+       bfd_boolean bfd_copy_private_header_data (bfd *ibfd, bfd *obfd);
+
+DESCRIPTION
+       Copy private BFD header information from the BFD @var{ibfd} to the
+       the BFD @var{obfd}.  This copies information that may require
+       sections to exist, but does not require symbol tables.  Return
+       <<true>> on success, <<false>> on error.
+       Possible error returns are:
+
+       o <<bfd_error_no_memory>> -
+       Not enough memory exists to create private data for @var{obfd}.
+
+.#define bfd_copy_private_header_data(ibfd, obfd) \
+.     BFD_SEND (obfd, _bfd_copy_private_header_data, \
+.              (ibfd, obfd))
+
+*/
+
+/*
+FUNCTION
+       bfd_copy_private_bfd_data
+
+SYNOPSIS
+       bfd_boolean bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd);
+
+DESCRIPTION
+       Copy private BFD information from the BFD @var{ibfd} to the
+       the BFD @var{obfd}.  Return <<TRUE>> on success, <<FALSE>> on error.
+       Possible error returns are:
+
+       o <<bfd_error_no_memory>> -
+       Not enough memory exists to create private data for @var{obfd}.
+
+.#define bfd_copy_private_bfd_data(ibfd, obfd) \
+.     BFD_SEND (obfd, _bfd_copy_private_bfd_data, \
+.              (ibfd, obfd))
+
+*/
+
+/*
+FUNCTION
+       bfd_merge_private_bfd_data
+
+SYNOPSIS
+       bfd_boolean bfd_merge_private_bfd_data (bfd *ibfd, bfd *obfd);
+
+DESCRIPTION
+       Merge private BFD information from the BFD @var{ibfd} to the
+       the output file BFD @var{obfd} when linking.  Return <<TRUE>>
+       on success, <<FALSE>> on error.  Possible error returns are:
+
+       o <<bfd_error_no_memory>> -
+       Not enough memory exists to create private data for @var{obfd}.
+
+.#define bfd_merge_private_bfd_data(ibfd, obfd) \
+.     BFD_SEND (obfd, _bfd_merge_private_bfd_data, \
+.              (ibfd, obfd))
+
+*/
+
+/*
+FUNCTION
+       bfd_set_private_flags
+
+SYNOPSIS
+       bfd_boolean bfd_set_private_flags (bfd *abfd, flagword flags);
+
+DESCRIPTION
+       Set private BFD flag information in the BFD @var{abfd}.
+       Return <<TRUE>> on success, <<FALSE>> on error.  Possible error
+       returns are:
+
+       o <<bfd_error_no_memory>> -
+       Not enough memory exists to create private data for @var{obfd}.
+
+.#define bfd_set_private_flags(abfd, flags) \
+.     BFD_SEND (abfd, _bfd_set_private_flags, (abfd, flags))
+
+*/
+
+/*
+FUNCTION
+       Other functions
+
+DESCRIPTION
+       The following functions exist but have not yet been documented.
+
+.#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, \
+.                 (abfd, syms, sec, off, file, func, line, NULL))
+.
+.#define bfd_find_nearest_line_discriminator(abfd, sec, syms, off, file, func, \
+.                                            line, disc) \
+.       BFD_SEND (abfd, _bfd_find_nearest_line, \
+.                 (abfd, syms, sec, off, file, func, line, disc))
+.
+.#define bfd_find_line(abfd, syms, sym, file, line) \
+.       BFD_SEND (abfd, _bfd_find_line, \
+.                 (abfd, syms, sym, file, line))
+.
+.#define bfd_find_inliner_info(abfd, file, func, line) \
+.       BFD_SEND (abfd, _bfd_find_inliner_info, \
+.                 (abfd, file, func, line))
+.
+.#define bfd_debug_info_start(abfd) \
+.       BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
+.
+.#define bfd_debug_info_end(abfd) \
+.       BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
+.
+.#define bfd_debug_info_accumulate(abfd, section) \
+.       BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
+.
+.#define bfd_stat_arch_elt(abfd, stat) \
+.       BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
+.
+.#define bfd_update_armap_timestamp(abfd) \
+.       BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd))
+.
+.#define bfd_set_arch_mach(abfd, arch, mach)\
+.       BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
+.
+.#define bfd_relax_section(abfd, section, link_info, again) \
+.       BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again))
+.
+.#define bfd_gc_sections(abfd, link_info) \
+.      BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info))
+.
+.#define bfd_lookup_section_flags(link_info, flag_info, section) \
+.      BFD_SEND (abfd, _bfd_lookup_section_flags, (link_info, flag_info, section))
+.
+.#define bfd_merge_sections(abfd, link_info) \
+.      BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info))
+.
+.#define bfd_is_group_section(abfd, sec) \
+.      BFD_SEND (abfd, _bfd_is_group_section, (abfd, sec))
+.
+.#define bfd_discard_group(abfd, sec) \
+.      BFD_SEND (abfd, _bfd_discard_group, (abfd, sec))
+.
+.#define bfd_link_hash_table_create(abfd) \
+.      BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
+.
+.#define bfd_link_add_symbols(abfd, info) \
+.      BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info))
+.
+.#define bfd_link_just_syms(abfd, sec, info) \
+.      BFD_SEND (abfd, _bfd_link_just_syms, (sec, info))
+.
+.#define bfd_final_link(abfd, info) \
+.      BFD_SEND (abfd, _bfd_final_link, (abfd, info))
+.
+.#define bfd_free_cached_info(abfd) \
+.       BFD_SEND (abfd, _bfd_free_cached_info, (abfd))
+.
+.#define bfd_get_dynamic_symtab_upper_bound(abfd) \
+.      BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd))
+.
+.#define bfd_print_private_bfd_data(abfd, file)\
+.      BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file))
+.
+.#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \
+.      BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols))
+.
+.#define bfd_get_synthetic_symtab(abfd, count, syms, dyncount, dynsyms, ret) \
+.      BFD_SEND (abfd, _bfd_get_synthetic_symtab, (abfd, count, syms, \
+.                                                  dyncount, dynsyms, ret))
+.
+.#define bfd_get_dynamic_reloc_upper_bound(abfd) \
+.      BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd))
+.
+.#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \
+.      BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms))
+.
+.extern bfd_byte *bfd_get_relocated_section_contents
+.  (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *,
+.   bfd_boolean, asymbol **);
+.
+
+*/
+
+bfd_byte *
+bfd_get_relocated_section_contents (bfd *abfd,
+                                   struct bfd_link_info *link_info,
+                                   struct bfd_link_order *link_order,
+                                   bfd_byte *data,
+                                   bfd_boolean relocatable,
+                                   asymbol **symbols)
+{
+  bfd *abfd2;
+  bfd_byte *(*fn) (bfd *, struct bfd_link_info *, struct bfd_link_order *,
+                  bfd_byte *, bfd_boolean, asymbol **);
+
+  if (link_order->type == bfd_indirect_link_order)
+    {
+      abfd2 = link_order->u.indirect.section->owner;
+      if (abfd2 == NULL)
+       abfd2 = abfd;
     }
+  else
+    abfd2 = abfd;
 
-    relocation += output_base +   reloc_target_input_section->output_offset;
-  }
+  fn = abfd2->xvec->_bfd_get_relocated_section_contents;
 
-  relocation += reloc_entry->addend ;
+  return (*fn) (abfd, link_info, link_order, data, relocatable, symbols);
+}
 
+/* Record information about an ELF program header.  */
+
+bfd_boolean
+bfd_record_phdr (bfd *abfd,
+                unsigned long type,
+                bfd_boolean flags_valid,
+                flagword flags,
+                bfd_boolean at_valid,
+                bfd_vma at,
+                bfd_boolean includes_filehdr,
+                bfd_boolean includes_phdrs,
+                unsigned int count,
+                asection **secs)
+{
+  struct elf_segment_map *m, **pm;
+  bfd_size_type amt;
+
+  if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+    return TRUE;
+
+  amt = sizeof (struct elf_segment_map);
+  amt += ((bfd_size_type) count - 1) * sizeof (asection *);
+  m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+  if (m == NULL)
+    return FALSE;
+
+  m->p_type = type;
+  m->p_flags = flags;
+  m->p_paddr = at;
+  m->p_flags_valid = flags_valid;
+  m->p_paddr_valid = at_valid;
+  m->includes_filehdr = includes_filehdr;
+  m->includes_phdrs = includes_phdrs;
+  m->count = count;
+  if (count > 0)
+    memcpy (m->sections, secs, count * sizeof (asection *));
+
+  for (pm = &elf_seg_map (abfd); *pm != NULL; pm = &(*pm)->next)
+    ;
+  *pm = m;
+
+  return TRUE;
+}
 
-  if(reloc_entry->address > (bfd_vma)(input_section->size)) 
-      {
-       return bfd_reloc_outofrange;
-      }
-         
+#ifdef BFD64
+/* Return true iff this target is 32-bit.  */
 
-  if (howto->pc_relative == true)
-      {
-       /*
-         Anything which started out as pc relative should end up that
-         way too. 
+static bfd_boolean
+is32bit (bfd *abfd)
+{
+  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+    {
+      const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+      return bed->s->elfclass == ELFCLASS32;
+    }
 
-         There are two ways we can see a pcrel instruction. Sometimes
-         the pcrel displacement has been partially calculated, it
-         includes the distance from the start of the section to the
-         instruction in it (eg sun3), and sometimes the field is
-         totally blank - eg m88kbcs.
-         */
+  /* For non-ELF targets, use architecture information.  */
+  return bfd_arch_bits_per_address (abfd) <= 32;
+}
+#endif
 
-       
-       relocation -= 
-         output_base +   input_section->output_offset;
+/* bfd_sprintf_vma and bfd_fprintf_vma display an address in the
+   target's address size.  */
 
-       if (howto->pcrel_offset == true) {
-         relocation -= reloc_entry->address;
-       }
+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);
+}
 
-      }
-
-  if (output_bfd!= (bfd *)NULL) {
-    if ( howto->partial_inplace == false)  {
-      /*
-       This is a partial relocation, and we want to apply the relocation
-       to the reloc entry rather than the raw data. Modify the reloc
-       inplace to reflect what we now know.
-       */
-      reloc_entry->addend = relocation  ;
-      reloc_entry->section = reloc_target_input_section;
-      if (reloc_target_input_section != (asection *)NULL) {
-       /* If we know the output section we can forget the symbol */
-       reloc_entry->sym_ptr_ptr = (asymbol**)NULL;
-      }
-      reloc_entry->address += 
-       input_section->output_offset;
-      return flag;
+void
+bfd_fprintf_vma (bfd *abfd ATTRIBUTE_UNUSED, void *stream, bfd_vma value)
+{
+#ifdef BFD64
+  if (is32bit (abfd))
+    {
+      fprintf ((FILE *) stream, "%08lx", (unsigned long) value & 0xffffffff);
+      return;
     }
-    else 
-       {
-         /* This is a partial relocation, but inplace, so modify the
-            reloc record a bit
-            */
+#endif
+  fprintf_vma ((FILE *) stream, value);
+}
 
-       }
-  }
-
-  reloc_entry->addend = 0;
-
-
-  /* 
-    Either we are relocating all the way, or we don't want to apply
-    the relocation to the reloc entry (probably because there isn't
-    any room in the output format to describe addends to relocs)
-    */
-  relocation >>= howto->rightshift;
-
-  /* Shift everything up to where it's going to be used */
-   
-  relocation <<= howto->bitpos;
-
-  /* Wait for the day when all have the mask in them */
-
-  /* What we do:
-     i instruction to be left alone
-     o offset within instruction
-     r relocation offset to apply
-     S src mask
-     D dst mask
-     N ~dst mask
-     A part 1
-     B part 2
-     R result
-     
-     Do this:
-     i i i i i o o o o o       from bfd_get<size>
-     and           S S S S S   to get the size offset we want
-     +   r r r r r r r r r r  to get the final value to place
-     and           D D D D D  to chop to right size
-     -----------------------
-     A A A A A 
-     And this:
-     ...   i i i i i o o o o o from bfd_get<size>
-     and   N N N N N           get instruction
-     -----------------------
-     ...   B B B B B
-     
-     And then:      
-     B B B B B       
-     or             A A A A A     
-     -----------------------
-     R R R R R R R R R R       put into bfd_put<size>
-     */
-
-#define DOIT(x) \
-  x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) +  relocation) & howto->dst_mask))
-
-    switch (howto->size)
+/*
+FUNCTION
+       bfd_alt_mach_code
+
+SYNOPSIS
+       bfd_boolean bfd_alt_mach_code (bfd *abfd, int alternative);
+
+DESCRIPTION
+
+       When more than one machine code number is available for the
+       same machine type, this function can be used to switch between
+       the preferred one (alternative == 0) and any others.  Currently,
+       only ELF supports this feature, with up to two alternate
+       machine codes.
+*/
+
+bfd_boolean
+bfd_alt_mach_code (bfd *abfd, int alternative)
+{
+  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+    {
+      int code;
+
+      switch (alternative)
        {
        case 0:
-           {
-             char x = bfd_get_8(abfd, (char *)data + addr);
-             DOIT(x);
-             bfd_put_8(abfd,x, (unsigned char *) data + addr);
-           }
+         code = get_elf_backend_data (abfd)->elf_machine_code;
          break;
 
        case 1:
-           { 
-             short x = bfd_get_16(abfd, (bfd_byte *)data + addr);
-             DOIT(x);
-             bfd_put_16(abfd, x,   (unsigned char *)data + addr);
-           }
+         code = get_elf_backend_data (abfd)->elf_machine_alt1;
+         if (code == 0)
+           return FALSE;
          break;
+
        case 2:
-           {
-             long  x = bfd_get_32(abfd, (bfd_byte *) data + addr);
-             DOIT(x);
-             bfd_put_32(abfd,x,    (bfd_byte *)data + addr);
-           }      
-         break;
-       case 3:
-         /* Do nothing */
+         code = get_elf_backend_data (abfd)->elf_machine_alt2;
+         if (code == 0)
+           return FALSE;
          break;
+
        default:
-         return bfd_reloc_other;
+         return FALSE;
        }
 
-  return flag;
+      elf_elfheader (abfd)->e_machine = code;
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+/*
+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_assert(file, line)
-char *file;
-int line;
+bfd_emul_set_maxpagesize (const char *emul, bfd_vma size)
 {
-  printf("bfd assertion fail %s:%d\n",file,line);
+  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.
 
-boolean
-bfd_set_start_address(abfd, vma)
-bfd *abfd;
-bfd_vma vma;
+RETURNS
+       Returns the common page size in bytes for ELF, 0 otherwise.
+*/
+
+bfd_vma
+bfd_emul_get_commonpagesize (const char *emul)
 {
-  abfd->start_address = vma;
-  return true;
+  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.
 
-bfd_vma bfd_log2(x)
-bfd_vma x;
+*/
+
+void
+bfd_emul_set_commonpagesize (const char *emul, bfd_vma size)
 {
-  bfd_vma  result = 0;
-  while ( (bfd_vma)(1<< result) < x)
-    result++;
-  return result;
+  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);
 }
 
-/* bfd_get_mtime:  Return cached file modification time (e.g. as read
-   from archive header for archive members, or from file system if we have
-   been called before); else determine modify time, cache it, and
-   return it.  */
+/*
+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.
+*/
 
-long
-bfd_get_mtime (abfd)
-     bfd *abfd;
+char *
+bfd_demangle (bfd *abfd, const char *name, int options)
 {
-  FILE *fp;
-  struct stat buf;
+  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;
+    }
 
-  if (abfd->mtime_set)
-    return abfd->mtime;
+  res = cplus_demangle (name, options);
 
-  fp = bfd_cache_lookup (abfd);
-  if (0 != fstat (fileno (fp), &buf))
-    return 0;
+  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;
+    }
 
-  abfd->mtime_set = true;
-  abfd->mtime = buf.st_mtime;
-  return abfd->mtime;
+  return res;
 }