comment fix
[deliverable/binutils-gdb.git] / bfd / reloc.c
index 487be0e767f6b80064918196cd7f28819e220df0..dbaef89ca8fa8bff5d29cb7fe4825a9bf6df5866 100644 (file)
@@ -1,5 +1,6 @@
 /* BFD support for handling relocation entries.
-   Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+   Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 1997
+   Free Software Foundation, Inc.
    Written by Cygnus Support.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -16,7 +17,7 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /*
 SECTION
@@ -41,6 +42,10 @@ SECTION
 @end menu
 
 */
+
+/* DO compile in the reloc_code name table from libbfd.h.  */
+#define _BFD_MAKE_TABLE_bfd_reloc_code_real
+
 #include "bfd.h"
 #include "sysdep.h"
 #include "bfdlink.h"
@@ -101,7 +106,7 @@ CODE_FRAGMENT
 .  bfd_vma addend;
 .
 .       {* Pointer to how to perform the required relocation *}
-.  const struct reloc_howto_struct *howto;
+.  reloc_howto_type *howto;
 .
 .} arelent;
 
@@ -134,7 +139,7 @@ DESCRIPTION
         type which modifies the bottom two bytes of a four byte word
         would not touch the first byte pointed to in a big endian
         world.
-       
+
        o <<addend>>
 
        The <<addend>> is a value provided by the back end to be added (!)
@@ -282,11 +287,9 @@ SUBSUBSECTION
 CODE_FRAGMENT
 .struct symbol_cache_entry;            {* Forward declaration *}
 .
-.typedef unsigned char bfd_byte;
-.
 .struct reloc_howto_struct
 .{
-.       {*  The type field has mainly a documetary use - the back end can
+.       {*  The type field has mainly a documentary use - the back end can
 .           do what it wants with it, though normally the back end's
 .           external idea of what a reloc number is stored
 .           in this field. For example, a PC relative word relocation
@@ -334,17 +337,6 @@ CODE_FRAGMENT
 .                                            bfd *output_bfd,
 .                                            char **error_message));
 .
-.
-.       {* If this field is non null, then the supplied function is
-.          called rather than the normal function. This is similar
-.         to special_function (previous), but takes different arguments,
-.          and is used for the new linking code. *}
-.  bfd_reloc_status_type (*special_function1)
-.                          PARAMS((const reloc_howto_type *howto,
-.                                  bfd *input_bfd,
-.                                  bfd_vma relocation,
-.                                  bfd_byte *location));
-.
 .       {* The textual name of the relocation type. *}
 .  char *name;
 .
@@ -376,7 +368,6 @@ CODE_FRAGMENT
 .  boolean pcrel_offset;
 .
 .};
-.typedef struct reloc_howto_struct reloc_howto_type;
 
 */
 
@@ -389,9 +380,7 @@ DESCRIPTION
 
 
 .#define HOWTO(C, R,S,B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \
-.  {(unsigned)C,R,S,B, P, BI, O,SF, 0,NAME,INPLACE,MASKSRC,MASKDST,PC}
-.#define HOWTO2(C, R,S,B, P, BI, O, SF, SF1,NAME, INPLACE, MASKSRC, MASKDST, PC) \
-.  {(unsigned)C,R,S,B, P, BI, O,SF, SF1,NAME,INPLACE,MASKSRC,MASKDST,PC}
+.  {(unsigned)C,R,S,B, P, BI, O,SF,NAME,INPLACE,MASKSRC,MASKDST,PC}
 
 DESCRIPTION
        And will be replaced with the totally magic way. But for the
@@ -422,7 +411,7 @@ FUNCTION
        bfd_get_reloc_size
 
 SYNOPSIS
-       int bfd_get_reloc_size (const reloc_howto_type *);
+       int bfd_get_reloc_size (reloc_howto_type *);
 
 DESCRIPTION
        For a reloc_howto_type that operates on a fixed number of bytes,
@@ -431,7 +420,7 @@ DESCRIPTION
 
 int
 bfd_get_reloc_size (howto)
-     const reloc_howto_type *howto;
+     reloc_howto_type *howto;
 {
   switch (howto->size)
     {
@@ -440,6 +429,7 @@ bfd_get_reloc_size (howto)
     case 2: return 4;
     case 3: return 0;
     case 4: return 8;
+    case 8: return 16;
     case -2: return 4;
     default: abort ();
     }
@@ -461,6 +451,110 @@ DESCRIPTION
 */
 
 
+/*
+FUNCTION
+       bfd_check_overflow
+
+SYNOPSIS
+       bfd_reloc_status_type
+               bfd_check_overflow
+                       (enum complain_overflow how,
+                        unsigned int bitsize,
+                        unsigned int rightshift,
+                        bfd_vma relocation);
+
+DESCRIPTION
+       Perform overflow checking on @var{relocation} which has @var{bitsize}
+       significant bits and will be shifted right by @var{rightshift} bits.
+       The result is either of @code{bfd_reloc_ok} or
+       @code{bfd_reloc_overflow}.
+
+*/
+
+bfd_reloc_status_type
+bfd_check_overflow (how, bitsize, rightshift, relocation)
+     enum complain_overflow how;
+     unsigned int bitsize, rightshift;
+     bfd_vma relocation;
+{
+  bfd_vma check;
+  bfd_reloc_status_type flag = bfd_reloc_ok;
+
+  /* Get the value that will be used for the relocation, but
+     starting at bit position zero.  */
+  check = relocation >> rightshift;
+
+  switch (how)
+    {
+    case complain_overflow_dont:
+      break;
+
+    case complain_overflow_signed:
+      {
+       /* Assumes two's complement.  */
+       bfd_signed_vma reloc_signed_max = (1 << (bitsize - 1)) - 1;
+       bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
+
+       /* The above right shift is incorrect for a signed value.
+          Fix it up by forcing on the upper bits.  */
+       if (rightshift > 0
+           && (bfd_signed_vma) relocation < 0)
+         check |= ((bfd_vma) - 1
+                   & ~((bfd_vma) - 1
+                       >> rightshift));
+       if ((bfd_signed_vma) check > reloc_signed_max
+           || (bfd_signed_vma) check < reloc_signed_min)
+         flag = bfd_reloc_overflow;
+      }
+      break;
+
+    case complain_overflow_unsigned:
+      {
+       /* Assumes two's complement.  This expression avoids
+          overflow if `bitsize' is the number of bits in
+          bfd_vma.  */
+       bfd_vma reloc_unsigned_max = (((1 << (bitsize - 1)) - 1) << 1) | 1;
+
+       if ((bfd_vma) check > reloc_unsigned_max)
+         flag = bfd_reloc_overflow;
+      }
+      break;
+
+    case complain_overflow_bitfield:
+      {
+       /* Assumes two's complement.  This expression avoids
+          overflow if `bitsize' is the number of bits in
+          bfd_vma.  */
+       bfd_vma reloc_bits = (((1 << (bitsize - 1)) - 1) << 1) | 1;
+
+       if (((bfd_vma) check & ~reloc_bits) != 0
+           && ((bfd_vma) check & ~reloc_bits) != (-1 & ~reloc_bits))
+         {
+           /* The above right shift is incorrect for a signed
+              value.  See if turning on the upper bits fixes the
+              overflow.  */
+           if (rightshift > 0
+               && (bfd_signed_vma) relocation < 0)
+             {
+               check |= ((bfd_vma) - 1
+                         & ~((bfd_vma) - 1
+                             >> rightshift));
+               if (((bfd_vma) check & ~reloc_bits) != (-1 & ~reloc_bits))
+                 flag = bfd_reloc_overflow;
+             }
+           else
+             flag = bfd_reloc_overflow;
+         }
+      }
+      break;
+
+    default:
+      abort ();
+    }
+
+  return flag;
+}
+
 
 /*
 FUNCTION
@@ -509,7 +603,7 @@ bfd_perform_relocation (abfd, reloc_entry, data, input_section, output_bfd,
   bfd_reloc_status_type flag = bfd_reloc_ok;
   bfd_size_type addr = reloc_entry->address;
   bfd_vma output_base = 0;
-  const reloc_howto_type *howto = reloc_entry->howto;
+  reloc_howto_type *howto = reloc_entry->howto;
   asection *reloc_target_output_section;
   asymbol *symbol;
 
@@ -633,6 +727,7 @@ bfd_perform_relocation (abfd, reloc_entry, data, input_section, output_bfd,
          /* WTF?? */
          if (abfd->xvec->flavour == bfd_target_coff_flavour
              && strcmp (abfd->xvec->name, "aixcoff-rs6000") != 0
+             && strcmp (abfd->xvec->name, "xcoff-powermac") != 0
              && strcmp (abfd->xvec->name, "coff-Intel-little") != 0
              && strcmp (abfd->xvec->name, "coff-Intel-big") != 0)
            {
@@ -728,79 +823,10 @@ space consuming.  For each target:
      machine word.
      FIXME: We should also do overflow checking on the result after
      adding in the value contained in the object file.  */
-  if (howto->complain_on_overflow != complain_overflow_dont)
-    {
-      bfd_vma check;
-
-      /* Get the value that will be used for the relocation, but
-        starting at bit position zero.  */
-      if (howto->rightshift > howto->bitpos)
-       check = relocation >> (howto->rightshift - howto->bitpos);
-      else
-       check = relocation << (howto->bitpos - howto->rightshift);
-      switch (howto->complain_on_overflow)
-       {
-       case complain_overflow_signed:
-         {
-           /* Assumes two's complement.  */
-           bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
-           bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
-
-           /* The above right shift is incorrect for a signed value.
-              Fix it up by forcing on the upper bits.  */
-           if (howto->rightshift > howto->bitpos
-               && (bfd_signed_vma) relocation < 0)
-             check |= ((bfd_vma) - 1
-                       & ~((bfd_vma) - 1
-                           >> (howto->rightshift - howto->bitpos)));
-           if ((bfd_signed_vma) check > reloc_signed_max
-               || (bfd_signed_vma) check < reloc_signed_min)
-             flag = bfd_reloc_overflow;
-         }
-         break;
-       case complain_overflow_unsigned:
-         {
-           /* Assumes two's complement.  This expression avoids
-              overflow if howto->bitsize is the number of bits in
-              bfd_vma.  */
-           bfd_vma reloc_unsigned_max =
-           (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
-
-           if ((bfd_vma) check > reloc_unsigned_max)
-             flag = bfd_reloc_overflow;
-         }
-         break;
-       case complain_overflow_bitfield:
-         {
-           /* Assumes two's complement.  This expression avoids
-              overflow if howto->bitsize is the number of bits in
-              bfd_vma.  */
-           bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
-
-           if (((bfd_vma) check & ~reloc_bits) != 0
-               && ((bfd_vma) check & ~reloc_bits) != (-1 & ~reloc_bits))
-             {
-               /* The above right shift is incorrect for a signed
-                  value.  See if turning on the upper bits fixes the
-                  overflow.  */
-               if (howto->rightshift > howto->bitpos
-                   && (bfd_signed_vma) relocation < 0)
-                 {
-                   check |= ((bfd_vma) - 1
-                             & ~((bfd_vma) - 1
-                                 >> (howto->rightshift - howto->bitpos)));
-                   if (((bfd_vma) check & ~reloc_bits) != (-1 & ~reloc_bits))
-                     flag = bfd_reloc_overflow;
-                 }
-               else
-                 flag = bfd_reloc_overflow;
-             }
-         }
-         break;
-       default:
-         abort ();
-       }
-    }
+  if (howto->complain_on_overflow != complain_overflow_dont
+      && flag == bfd_reloc_ok)
+    flag = bfd_check_overflow (howto->complain_on_overflow, howto->bitsize,
+                              howto->rightshift, relocation);
 
   /*
     Either we are relocating all the way, or we don't want to apply
@@ -884,20 +910,18 @@ space consuming.  For each target:
       break;
 
     case 1:
-      if (relocation)
-       {
-         short x = bfd_get_16 (abfd, (bfd_byte *) data + addr);
-         DOIT (x);
-         bfd_put_16 (abfd, x, (unsigned char *) data + addr);
-       }
+      {
+       short x = bfd_get_16 (abfd, (bfd_byte *) data + addr);
+       DOIT (x);
+       bfd_put_16 (abfd, x, (unsigned char *) data + addr);
+      }
       break;
     case 2:
-      if (relocation)
-       {
-         long x = bfd_get_32 (abfd, (bfd_byte *) data + addr);
-         DOIT (x);
-         bfd_put_32 (abfd, x, (bfd_byte *) data + addr);
-       }
+      {
+       long x = bfd_get_32 (abfd, (bfd_byte *) data + addr);
+       DOIT (x);
+       bfd_put_32 (abfd, x, (bfd_byte *) data + addr);
+      }
       break;
     case -2:
       {
@@ -908,18 +932,26 @@ space consuming.  For each target:
       }
       break;
 
+    case -1:
+      {
+       long x = bfd_get_16 (abfd, (bfd_byte *) data + addr);
+       relocation = -relocation;
+       DOIT (x);
+       bfd_put_16 (abfd, x, (bfd_byte *) data + addr);
+      }
+      break;
+
     case 3:
       /* Do nothing */
       break;
 
     case 4:
 #ifdef BFD64
-      if (relocation)
-       {
-         bfd_vma x = bfd_get_64 (abfd, (bfd_byte *) data + addr);
-         DOIT (x);
-         bfd_put_64 (abfd, x, (bfd_byte *) data + addr);
-       }
+      {
+       bfd_vma x = bfd_get_64 (abfd, (bfd_byte *) data + addr);
+       DOIT (x);
+       bfd_put_64 (abfd, x, (bfd_byte *) data + addr);
+      }
 #else
       abort ();
 #endif
@@ -931,14 +963,391 @@ space consuming.  For each target:
   return flag;
 }
 
+/*
+FUNCTION
+       bfd_install_relocation
+
+SYNOPSIS
+       bfd_reloc_status_type
+                bfd_install_relocation
+                        (bfd *abfd,
+                         arelent *reloc_entry,
+                         PTR data, bfd_vma data_start,
+                         asection *input_section,
+                        char **error_message);
+
+DESCRIPTION
+       This looks remarkably like <<bfd_perform_relocation>>, except it
+       does not expect that the section contents have been filled in.
+       I.e., it's suitable for use when creating, rather than applying
+       a relocation.
+
+       For now, this function should be considered reserved for the
+       assembler.
+
+*/
+
+
+bfd_reloc_status_type
+bfd_install_relocation (abfd, reloc_entry, data_start, data_start_offset,
+                       input_section, error_message)
+     bfd *abfd;
+     arelent *reloc_entry;
+     PTR data_start;
+     bfd_vma data_start_offset;
+     asection *input_section;
+     char **error_message;
+{
+  bfd_vma relocation;
+  bfd_reloc_status_type flag = bfd_reloc_ok;
+  bfd_size_type addr = reloc_entry->address;
+  bfd_vma output_base = 0;
+  reloc_howto_type *howto = reloc_entry->howto;
+  asection *reloc_target_output_section;
+  asymbol *symbol;
+  bfd_byte *data;
+
+  symbol = *(reloc_entry->sym_ptr_ptr);
+  if (bfd_is_abs_section (symbol->section))
+    {
+      reloc_entry->address += input_section->output_offset;
+      return bfd_reloc_ok;
+    }
+
+  /* If there is a function supplied to handle this relocation type,
+     call it.  It'll return `bfd_reloc_continue' if further processing
+     can be done.  */
+  if (howto->special_function)
+    {
+      bfd_reloc_status_type cont;
+  
+      /* XXX - The special_function calls haven't been fixed up to deal
+        with creating new relocations and section contents.  */
+      cont = howto->special_function (abfd, reloc_entry, symbol,
+                                     /* XXX - Non-portable! */
+                                     ((bfd_byte *) data_start
+                                      - data_start_offset),
+                                     input_section, abfd, error_message);
+      if (cont != bfd_reloc_continue)
+       return cont;
+    }
+
+  /* Is the address of the relocation really within the section?  */
+  if (reloc_entry->address > input_section->_cooked_size)
+    return bfd_reloc_outofrange;
+
+  /* Work out which section the relocation is targetted at and the
+     initial relocation command value.  */
+
+  /* Get symbol value.  (Common symbols are special.)  */
+  if (bfd_is_com_section (symbol->section))
+    relocation = 0;
+  else
+    relocation = symbol->value;
+
+  reloc_target_output_section = symbol->section->output_section;
+
+  /* Convert input-section-relative symbol value to absolute.  */
+  if (howto->partial_inplace == false)
+    output_base = 0;
+  else
+    output_base = reloc_target_output_section->vma;
+
+  relocation += output_base + symbol->section->output_offset;
+
+  /* Add in supplied addend.  */
+  relocation += reloc_entry->addend;
+
+  /* Here the variable relocation holds the final address of the
+     symbol we are relocating against, plus any addend.  */
+
+  if (howto->pc_relative == true)
+    {
+      /* This is a PC relative relocation.  We want to set RELOCATION
+        to the distance between the address of the symbol and the
+        location.  RELOCATION is already the address of the symbol.
+
+        We start by subtracting the address of the section containing
+        the location.
+
+        If pcrel_offset is set, we must further subtract the position
+        of the location within the section.  Some targets arrange for
+        the addend to be the negative of the position of the location
+        within the section; for example, i386-aout does this.  For
+        i386-aout, pcrel_offset is false.  Some other targets do not
+        include the position of the location; for example, m88kbcs,
+        or ELF.  For those targets, pcrel_offset is true.
+
+        If we are producing relocateable output, then we must ensure
+        that this reloc will be correctly computed when the final
+        relocation is done.  If pcrel_offset is false we want to wind
+        up with the negative of the location within the section,
+        which means we must adjust the existing addend by the change
+        in the location within the section.  If pcrel_offset is true
+        we do not want to adjust the existing addend at all.
+
+        FIXME: This seems logical to me, but for the case of
+        producing relocateable output it is not what the code
+        actually does.  I don't want to change it, because it seems
+        far too likely that something will break.  */
+
+      relocation -=
+       input_section->output_section->vma + input_section->output_offset;
+
+      if (howto->pcrel_offset == true && howto->partial_inplace == true)
+       relocation -= reloc_entry->address;
+    }
+
+  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->address += input_section->output_offset;
+      return flag;
+    }
+  else
+    {
+      /* This is a partial relocation, but inplace, so modify the
+        reloc record a bit.
+
+        If we've relocated with a symbol with a section, change
+        into a ref to the section belonging to the symbol.  */
+
+      reloc_entry->address += input_section->output_offset;
+
+      /* WTF?? */
+      if (abfd->xvec->flavour == bfd_target_coff_flavour
+         && strcmp (abfd->xvec->name, "aixcoff-rs6000") != 0
+         && strcmp (abfd->xvec->name, "xcoff-powermac") != 0
+         && strcmp (abfd->xvec->name, "coff-Intel-little") != 0
+         && strcmp (abfd->xvec->name, "coff-Intel-big") != 0)
+       {
+#if 1
+/* For m68k-coff, the addend was being subtracted twice during
+   relocation with -r.  Removing the line below this comment
+   fixes that problem; see PR 2953.
+
+However, Ian wrote the following, regarding removing the line below,
+which explains why it is still enabled:  --djm
+
+If you put a patch like that into BFD you need to check all the COFF
+linkers.  I am fairly certain that patch will break coff-i386 (e.g.,
+SCO); see coff_i386_reloc in coff-i386.c where I worked around the
+problem in a different way.  There may very well be a reason that the
+code works as it does.
+
+Hmmm.  The first obvious point is that bfd_install_relocation should
+not have any tests that depend upon the flavour.  It's seem like
+entirely the wrong place for such a thing.  The second obvious point
+is that the current code ignores the reloc addend when producing
+relocateable output for COFF.  That's peculiar.  In fact, I really
+have no idea what the point of the line you want to remove is.
+
+A typical COFF reloc subtracts the old value of the symbol and adds in
+the new value to the location in the object file (if it's a pc
+relative reloc it adds the difference between the symbol value and the
+location).  When relocating we need to preserve that property.
+
+BFD handles this by setting the addend to the negative of the old
+value of the symbol.  Unfortunately it handles common symbols in a
+non-standard way (it doesn't subtract the old value) but that's a
+different story (we can't change it without losing backward
+compatibility with old object files) (coff-i386 does subtract the old
+value, to be compatible with existing coff-i386 targets, like SCO).
+
+So everything works fine when not producing relocateable output.  When
+we are producing relocateable output, logically we should do exactly
+what we do when not producing relocateable output.  Therefore, your
+patch is correct.  In fact, it should probably always just set
+reloc_entry->addend to 0 for all cases, since it is, in fact, going to
+add the value into the object file.  This won't hurt the COFF code,
+which doesn't use the addend; I'm not sure what it will do to other
+formats (the thing to check for would be whether any formats both use
+the addend and set partial_inplace).
+
+When I wanted to make coff-i386 produce relocateable output, I ran
+into the problem that you are running into: I wanted to remove that
+line.  Rather than risk it, I made the coff-i386 relocs use a special
+function; it's coff_i386_reloc in coff-i386.c.  The function
+specifically adds the addend field into the object file, knowing that
+bfd_install_relocation is not going to.  If you remove that line, then
+coff-i386.c will wind up adding the addend field in twice.  It's
+trivial to fix; it just needs to be done.
+
+The problem with removing the line is just that it may break some
+working code.  With BFD it's hard to be sure of anything.  The right
+way to deal with this is simply to build and test at least all the
+supported COFF targets.  It should be straightforward if time and disk
+space consuming.  For each target:
+    1) build the linker
+    2) generate some executable, and link it using -r (I would
+       probably use paranoia.o and link against newlib/libc.a, which
+       for all the supported targets would be available in
+       /usr/cygnus/progressive/H-host/target/lib/libc.a).
+    3) make the change to reloc.c
+    4) rebuild the linker
+    5) repeat step 2
+    6) if the resulting object files are the same, you have at least
+       made it no worse
+    7) if they are different you have to figure out which version is
+       right
+*/
+         relocation -= reloc_entry->addend;
+#endif
+         reloc_entry->addend = 0;
+       }
+      else
+       {
+         reloc_entry->addend = relocation;
+       }
+    }
+
+  /* FIXME: This overflow checking is incomplete, because the value
+     might have overflowed before we get here.  For a correct check we
+     need to compute the value in a size larger than bitsize, but we
+     can't reasonably do that for a reloc the same size as a host
+     machine word.
+     FIXME: We should also do overflow checking on the result after
+     adding in the value contained in the object file.  */
+  if (howto->complain_on_overflow != complain_overflow_dont)
+    flag = bfd_check_overflow (howto->complain_on_overflow, howto->bitsize,
+                              howto->rightshift, relocation);
+
+  /*
+    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)
+    */
+
+  /* The cast to bfd_vma avoids a bug in the Alpha OSF/1 C compiler
+     (OSF version 1.3, compiler version 3.11).  It miscompiles the
+     following program:
+
+     struct str
+     {
+       unsigned int i0;
+     } s = { 0 };
+
+     int
+     main ()
+     {
+       unsigned long x;
+
+       x = 0x100000000;
+       x <<= (unsigned long) s.i0;
+       if (x == 0)
+        printf ("failed\n");
+       else
+        printf ("succeeded (%lx)\n", x);
+     }
+     */
+
+  relocation >>= (bfd_vma) howto->rightshift;
+
+  /* Shift everything up to where it's going to be used */
+
+  relocation <<= (bfd_vma) 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))
+
+  data = (bfd_byte *) data_start + (addr - data_start_offset);
+
+  switch (howto->size)
+    {
+    case 0:
+      {
+       char x = bfd_get_8 (abfd, (char *) data);
+       DOIT (x);
+       bfd_put_8 (abfd, x, (unsigned char *) data);
+      }
+      break;
+
+    case 1:
+      {
+       short x = bfd_get_16 (abfd, (bfd_byte *) data);
+       DOIT (x);
+       bfd_put_16 (abfd, x, (unsigned char *) data);
+      }
+      break;
+    case 2:
+      {
+       long x = bfd_get_32 (abfd, (bfd_byte *) data);
+       DOIT (x);
+       bfd_put_32 (abfd, x, (bfd_byte *) data);
+      }
+      break;
+    case -2:
+      {
+       long x = bfd_get_32 (abfd, (bfd_byte *) data);
+       relocation = -relocation;
+       DOIT (x);
+       bfd_put_32 (abfd, x, (bfd_byte *) data);
+      }
+      break;
+
+    case 3:
+      /* Do nothing */
+      break;
+
+    case 4:
+      {
+       bfd_vma x = bfd_get_64 (abfd, (bfd_byte *) data);
+       DOIT (x);
+       bfd_put_64 (abfd, x, (bfd_byte *) data);
+      }
+      break;
+    default:
+      return bfd_reloc_other;
+    }
+
+  return flag;
+}
+
 /* This relocation routine is used by some of the backend linkers.
    They do not construct asymbol or arelent structures, so there is no
    reason for them to use bfd_perform_relocation.  Also,
    bfd_perform_relocation is so hacked up it is easier to write a new
    function than to try to deal with it.
 
-   This routine does a final relocation.  It should not be used when
-   generating relocateable output.
+   This routine does a final relocation.  Whether it is useful for a
+   relocateable link depends upon how the object format defines
+   relocations.
 
    FIXME: This routine ignores any special_function in the HOWTO,
    since the existing special_function values have been written for
@@ -955,7 +1364,7 @@ space consuming.  For each target:
 bfd_reloc_status_type
 _bfd_final_link_relocate (howto, input_bfd, input_section, contents, address,
                          value, addend)
-     const reloc_howto_type *howto;
+     reloc_howto_type *howto;
      bfd *input_bfd;
      asection *input_section;
      bfd_byte *contents;
@@ -966,7 +1375,7 @@ _bfd_final_link_relocate (howto, input_bfd, input_section, contents, address,
   bfd_vma relocation;
 
   /* Sanity check the address.  */
-  if (address > input_section->_cooked_size)
+  if (address > input_section->_raw_size)
     return bfd_reloc_outofrange;
 
   /* This function assumes that we are dealing with a basic relocation
@@ -993,13 +1402,6 @@ _bfd_final_link_relocate (howto, input_bfd, input_section, contents, address,
        relocation -= address;
     }
 
-  if(howto->special_function1) {
-      bfd_reloc_status_type cont;
-      cont = (*howto->special_function1)(howto, input_bfd, relocation,
-                                      contents + address);
-      if (cont != bfd_reloc_continue)
-       return cont;
-    }
   return _bfd_relocate_contents (howto, input_bfd, relocation,
                                 contents + address);
 }
@@ -1008,7 +1410,7 @@ _bfd_final_link_relocate (howto, input_bfd, input_section, contents, address,
 
 bfd_reloc_status_type
 _bfd_relocate_contents (howto, input_bfd, relocation, location)
-     const reloc_howto_type *howto;
+     reloc_howto_type *howto;
      bfd *input_bfd;
      bfd_vma relocation;
      bfd_byte *location;
@@ -1222,204 +1624,844 @@ DESCRIPTION
        enumerator value; you can't get a howto pointer from a random set
        of attributes.
 
+SENUM
+   bfd_reloc_code_real
+
+ENUM
+  BFD_RELOC_64
+ENUMX
+  BFD_RELOC_32
+ENUMX
+  BFD_RELOC_26
+ENUMX
+  BFD_RELOC_24
+ENUMX
+  BFD_RELOC_16
+ENUMX
+  BFD_RELOC_14
+ENUMX
+  BFD_RELOC_8
+ENUMDOC
+  Basic absolute relocations of N bits.
+
+ENUM
+  BFD_RELOC_64_PCREL
+ENUMX
+  BFD_RELOC_32_PCREL
+ENUMX
+  BFD_RELOC_24_PCREL
+ENUMX
+  BFD_RELOC_16_PCREL
+ENUMX
+  BFD_RELOC_12_PCREL
+ENUMX
+  BFD_RELOC_8_PCREL
+ENUMDOC
+  PC-relative relocations.  Sometimes these are relative to the address
+of the relocation itself; sometimes they are relative to the start of
+the section containing the relocation.  It depends on the specific target.
+
+The 24-bit relocation is used in some Intel 960 configurations.
+
+ENUM
+  BFD_RELOC_32_GOT_PCREL
+ENUMX
+  BFD_RELOC_16_GOT_PCREL
+ENUMX
+  BFD_RELOC_8_GOT_PCREL
+ENUMX
+  BFD_RELOC_32_GOTOFF
+ENUMX
+  BFD_RELOC_16_GOTOFF
+ENUMX
+  BFD_RELOC_LO16_GOTOFF
+ENUMX
+  BFD_RELOC_HI16_GOTOFF
+ENUMX
+  BFD_RELOC_HI16_S_GOTOFF
+ENUMX
+  BFD_RELOC_8_GOTOFF
+ENUMX
+  BFD_RELOC_32_PLT_PCREL
+ENUMX
+  BFD_RELOC_24_PLT_PCREL
+ENUMX
+  BFD_RELOC_16_PLT_PCREL
+ENUMX
+  BFD_RELOC_8_PLT_PCREL
+ENUMX
+  BFD_RELOC_32_PLTOFF
+ENUMX
+  BFD_RELOC_16_PLTOFF
+ENUMX
+  BFD_RELOC_LO16_PLTOFF
+ENUMX
+  BFD_RELOC_HI16_PLTOFF
+ENUMX
+  BFD_RELOC_HI16_S_PLTOFF
+ENUMX
+  BFD_RELOC_8_PLTOFF
+ENUMDOC
+  For ELF.
+
+ENUM
+  BFD_RELOC_68K_GLOB_DAT
+ENUMX
+  BFD_RELOC_68K_JMP_SLOT
+ENUMX
+  BFD_RELOC_68K_RELATIVE
+ENUMDOC
+  Relocations used by 68K ELF.
+
+ENUM
+  BFD_RELOC_32_BASEREL
+ENUMX
+  BFD_RELOC_16_BASEREL
+ENUMX
+  BFD_RELOC_LO16_BASEREL
+ENUMX
+  BFD_RELOC_HI16_BASEREL
+ENUMX
+  BFD_RELOC_HI16_S_BASEREL
+ENUMX
+  BFD_RELOC_8_BASEREL
+ENUMX
+  BFD_RELOC_RVA
+ENUMDOC
+  Linkage-table relative.
+
+ENUM
+  BFD_RELOC_8_FFnn
+ENUMDOC
+  Absolute 8-bit relocation, but used to form an address like 0xFFnn.
+
+ENUM
+  BFD_RELOC_32_PCREL_S2
+ENUMX
+  BFD_RELOC_16_PCREL_S2
+ENUMX
+  BFD_RELOC_23_PCREL_S2
+ENUMDOC
+  These PC-relative relocations are stored as word displacements --
+i.e., byte displacements shifted right two bits.  The 30-bit word
+displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the
+SPARC.  (SPARC tools generally refer to this as <<WDISP30>>.)  The
+signed 16-bit displacement is used on the MIPS, and the 23-bit
+displacement is used on the Alpha.
+
+ENUM
+  BFD_RELOC_HI22
+ENUMX
+  BFD_RELOC_LO10
+ENUMDOC
+  High 22 bits and low 10 bits of 32-bit value, placed into lower bits of
+the target word.  These are used on the SPARC.
+
+ENUM
+  BFD_RELOC_GPREL16
+ENUMX
+  BFD_RELOC_GPREL32
+ENUMDOC
+  For systems that allocate a Global Pointer register, these are
+displacements off that register.  These relocation types are
+handled specially, because the value the register will have is
+decided relatively late.
+
+
+ENUM
+  BFD_RELOC_I960_CALLJ
+ENUMDOC
+  Reloc types used for i960/b.out.
+
+ENUM
+  BFD_RELOC_NONE
+ENUMX
+  BFD_RELOC_SPARC_WDISP22
+ENUMX
+  BFD_RELOC_SPARC22
+ENUMX
+  BFD_RELOC_SPARC13
+ENUMX
+  BFD_RELOC_SPARC_GOT10
+ENUMX
+  BFD_RELOC_SPARC_GOT13
+ENUMX
+  BFD_RELOC_SPARC_GOT22
+ENUMX
+  BFD_RELOC_SPARC_PC10
+ENUMX
+  BFD_RELOC_SPARC_PC22
+ENUMX
+  BFD_RELOC_SPARC_WPLT30
+ENUMX
+  BFD_RELOC_SPARC_COPY
+ENUMX
+  BFD_RELOC_SPARC_GLOB_DAT
+ENUMX
+  BFD_RELOC_SPARC_JMP_SLOT
+ENUMX
+  BFD_RELOC_SPARC_RELATIVE
+ENUMX
+  BFD_RELOC_SPARC_UA32
+ENUMDOC
+  SPARC ELF relocations.  There is probably some overlap with other
+  relocation types already defined.
+
+ENUM
+  BFD_RELOC_SPARC_BASE13
+ENUMX
+  BFD_RELOC_SPARC_BASE22
+ENUMDOC
+  I think these are specific to SPARC a.out (e.g., Sun 4).
+
+ENUMEQ
+  BFD_RELOC_SPARC_64
+  BFD_RELOC_64
+ENUMX
+  BFD_RELOC_SPARC_10
+ENUMX
+  BFD_RELOC_SPARC_11
+ENUMX
+  BFD_RELOC_SPARC_OLO10
+ENUMX
+  BFD_RELOC_SPARC_HH22
+ENUMX
+  BFD_RELOC_SPARC_HM10
+ENUMX
+  BFD_RELOC_SPARC_LM22
+ENUMX
+  BFD_RELOC_SPARC_PC_HH22
+ENUMX
+  BFD_RELOC_SPARC_PC_HM10
+ENUMX
+  BFD_RELOC_SPARC_PC_LM22
+ENUMX
+  BFD_RELOC_SPARC_WDISP16
+ENUMX
+  BFD_RELOC_SPARC_WDISP19
+ENUMX
+  BFD_RELOC_SPARC_7
+ENUMX
+  BFD_RELOC_SPARC_6
+ENUMX
+  BFD_RELOC_SPARC_5
+ENUMEQX
+  BFD_RELOC_SPARC_DISP64
+  BFD_RELOC_64_PCREL
+ENUMX
+  BFD_RELOC_SPARC_PLT64
+ENUMX
+  BFD_RELOC_SPARC_HIX22
+ENUMX
+  BFD_RELOC_SPARC_LOX10
+ENUMX
+  BFD_RELOC_SPARC_H44
+ENUMX
+  BFD_RELOC_SPARC_M44
+ENUMX
+  BFD_RELOC_SPARC_L44
+ENUMX
+  BFD_RELOC_SPARC_REGISTER
+ENUMDOC
+  SPARC64 relocations
+
+ENUM
+  BFD_RELOC_ALPHA_GPDISP_HI16
+ENUMDOC
+  Alpha ECOFF and ELF relocations.  Some of these treat the symbol or
+     "addend" in some special way.
+  For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when
+     writing; when reading, it will be the absolute section symbol.  The
+     addend is the displacement in bytes of the "lda" instruction from
+     the "ldah" instruction (which is at the address of this reloc).
+ENUM
+  BFD_RELOC_ALPHA_GPDISP_LO16
+ENUMDOC
+  For GPDISP_LO16 ("ignore") relocations, the symbol is handled as
+     with GPDISP_HI16 relocs.  The addend is ignored when writing the
+     relocations out, and is filled in with the file's GP value on
+     reading, for convenience.
+
+ENUM
+  BFD_RELOC_ALPHA_GPDISP
+ENUMDOC
+  The ELF GPDISP relocation is exactly the same as the GPDISP_HI16
+     relocation except that there is no accompanying GPDISP_LO16
+     relocation.
+
+ENUM
+  BFD_RELOC_ALPHA_LITERAL
+ENUMX
+  BFD_RELOC_ALPHA_ELF_LITERAL
+ENUMX
+  BFD_RELOC_ALPHA_LITUSE
+ENUMDOC
+  The Alpha LITERAL/LITUSE relocs are produced by a symbol reference;
+     the assembler turns it into a LDQ instruction to load the address of
+     the symbol, and then fills in a register in the real instruction.
+
+     The LITERAL reloc, at the LDQ instruction, refers to the .lita
+     section symbol.  The addend is ignored when writing, but is filled
+     in with the file's GP value on reading, for convenience, as with the
+     GPDISP_LO16 reloc.
+
+     The ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16.
+     It should refer to the symbol to be referenced, as with 16_GOTOFF,
+     but it generates output not based on the position within the .got
+     section, but relative to the GP value chosen for the file during the
+     final link stage.
+
+     The LITUSE reloc, on the instruction using the loaded address, gives
+     information to the linker that it might be able to use to optimize
+     away some literal section references.  The symbol is ignored (read
+     as the absolute section symbol), and the "addend" indicates the type
+     of instruction using the register:
+              1 - "memory" fmt insn
+              2 - byte-manipulation (byte offset reg)
+              3 - jsr (target of branch)
+
+     The GNU linker currently doesn't do any of this optimizing.
+
+ENUM
+  BFD_RELOC_ALPHA_HINT
+ENUMDOC
+  The HINT relocation indicates a value that should be filled into the
+     "hint" field of a jmp/jsr/ret instruction, for possible branch-
+     prediction logic which may be provided on some processors.
+
+ENUM
+  BFD_RELOC_ALPHA_LINKAGE
+ENUMDOC
+  The LINKAGE relocation outputs a linkage pair in the object file,
+     which is filled by the linker.
+
+ENUM
+  BFD_RELOC_ALPHA_CODEADDR
+ENUMDOC
+  The CODEADDR relocation outputs a STO_CA in the object file,
+     which is filled by the linker.
+
+ENUM
+  BFD_RELOC_MIPS_JMP
+ENUMDOC
+  Bits 27..2 of the relocation address shifted right 2 bits;
+     simple reloc otherwise.
+
+ENUM
+  BFD_RELOC_MIPS16_JMP
+ENUMDOC
+  The MIPS16 jump instruction.
+
+ENUM
+  BFD_RELOC_MIPS16_GPREL
+ENUMDOC
+  MIPS16 GP relative reloc.
+
+ENUM
+  BFD_RELOC_HI16
+ENUMDOC
+  High 16 bits of 32-bit value; simple reloc.
+ENUM
+  BFD_RELOC_HI16_S
+ENUMDOC
+  High 16 bits of 32-bit value but the low 16 bits will be sign
+     extended and added to form the final result.  If the low 16
+     bits form a negative number, we need to add one to the high value
+     to compensate for the borrow when the low bits are added.
+ENUM
+  BFD_RELOC_LO16
+ENUMDOC
+  Low 16 bits.
+ENUM
+  BFD_RELOC_PCREL_HI16_S
+ENUMDOC
+  Like BFD_RELOC_HI16_S, but PC relative.
+ENUM
+  BFD_RELOC_PCREL_LO16
+ENUMDOC
+  Like BFD_RELOC_LO16, but PC relative.
+
+ENUMEQ
+  BFD_RELOC_MIPS_GPREL
+  BFD_RELOC_GPREL16
+ENUMDOC
+  Relocation relative to the global pointer.
+
+ENUM
+  BFD_RELOC_MIPS_LITERAL
+ENUMDOC
+  Relocation against a MIPS literal section.
+
+ENUM
+  BFD_RELOC_MIPS_GOT16
+ENUMX
+  BFD_RELOC_MIPS_CALL16
+ENUMEQX
+  BFD_RELOC_MIPS_GPREL32
+  BFD_RELOC_GPREL32
+ENUMX
+  BFD_RELOC_MIPS_GOT_HI16
+ENUMX
+  BFD_RELOC_MIPS_GOT_LO16
+ENUMX
+  BFD_RELOC_MIPS_CALL_HI16
+ENUMX
+  BFD_RELOC_MIPS_CALL_LO16
+ENUMDOC
+  MIPS ELF relocations.
+
+ENUM
+  BFD_RELOC_386_GOT32
+ENUMX
+  BFD_RELOC_386_PLT32
+ENUMX
+  BFD_RELOC_386_COPY
+ENUMX
+  BFD_RELOC_386_GLOB_DAT
+ENUMX
+  BFD_RELOC_386_JUMP_SLOT
+ENUMX
+  BFD_RELOC_386_RELATIVE
+ENUMX
+  BFD_RELOC_386_GOTOFF
+ENUMX
+  BFD_RELOC_386_GOTPC
+ENUMDOC
+  i386/elf relocations
+
+ENUM
+  BFD_RELOC_NS32K_IMM_8
+ENUMX
+  BFD_RELOC_NS32K_IMM_16
+ENUMX
+  BFD_RELOC_NS32K_IMM_32
+ENUMX
+  BFD_RELOC_NS32K_IMM_8_PCREL
+ENUMX
+  BFD_RELOC_NS32K_IMM_16_PCREL
+ENUMX
+  BFD_RELOC_NS32K_IMM_32_PCREL
+ENUMX
+  BFD_RELOC_NS32K_DISP_8
+ENUMX
+  BFD_RELOC_NS32K_DISP_16
+ENUMX
+  BFD_RELOC_NS32K_DISP_32
+ENUMX
+  BFD_RELOC_NS32K_DISP_8_PCREL
+ENUMX
+  BFD_RELOC_NS32K_DISP_16_PCREL
+ENUMX
+  BFD_RELOC_NS32K_DISP_32_PCREL
+ENUMDOC
+  ns32k relocations
+
+ENUM
+  BFD_RELOC_PPC_B26
+ENUMX
+  BFD_RELOC_PPC_BA26
+ENUMX
+  BFD_RELOC_PPC_TOC16
+ENUMX
+  BFD_RELOC_PPC_B16
+ENUMX
+  BFD_RELOC_PPC_B16_BRTAKEN
+ENUMX
+  BFD_RELOC_PPC_B16_BRNTAKEN
+ENUMX
+  BFD_RELOC_PPC_BA16
+ENUMX
+  BFD_RELOC_PPC_BA16_BRTAKEN
+ENUMX
+  BFD_RELOC_PPC_BA16_BRNTAKEN
+ENUMX
+  BFD_RELOC_PPC_COPY
+ENUMX
+  BFD_RELOC_PPC_GLOB_DAT
+ENUMX
+  BFD_RELOC_PPC_JMP_SLOT
+ENUMX
+  BFD_RELOC_PPC_RELATIVE
+ENUMX
+  BFD_RELOC_PPC_LOCAL24PC
+ENUMX
+  BFD_RELOC_PPC_EMB_NADDR32
+ENUMX
+  BFD_RELOC_PPC_EMB_NADDR16
+ENUMX
+  BFD_RELOC_PPC_EMB_NADDR16_LO
+ENUMX
+  BFD_RELOC_PPC_EMB_NADDR16_HI
+ENUMX
+  BFD_RELOC_PPC_EMB_NADDR16_HA
+ENUMX
+  BFD_RELOC_PPC_EMB_SDAI16
+ENUMX
+  BFD_RELOC_PPC_EMB_SDA2I16
+ENUMX
+  BFD_RELOC_PPC_EMB_SDA2REL
+ENUMX
+  BFD_RELOC_PPC_EMB_SDA21
+ENUMX
+  BFD_RELOC_PPC_EMB_MRKREF
+ENUMX
+  BFD_RELOC_PPC_EMB_RELSEC16
+ENUMX
+  BFD_RELOC_PPC_EMB_RELST_LO
+ENUMX
+  BFD_RELOC_PPC_EMB_RELST_HI
+ENUMX
+  BFD_RELOC_PPC_EMB_RELST_HA
+ENUMX
+  BFD_RELOC_PPC_EMB_BIT_FLD
+ENUMX
+  BFD_RELOC_PPC_EMB_RELSDA
+ENUMDOC
+  Power(rs6000) and PowerPC relocations.
+
+ENUM
+  BFD_RELOC_CTOR
+ENUMDOC
+  The type of reloc used to build a contructor table - at the moment
+  probably a 32 bit wide absolute relocation, but the target can choose.
+  It generally does map to one of the other relocation types.
+
+ENUM
+  BFD_RELOC_ARM_PCREL_BRANCH
+ENUMDOC
+  ARM 26 bit pc-relative branch.  The lowest two bits must be zero and are
+  not stored in the instruction.
+ENUM
+  BFD_RELOC_ARM_IMMEDIATE
+ENUMX
+  BFD_RELOC_ARM_OFFSET_IMM
+ENUMX
+  BFD_RELOC_ARM_SHIFT_IMM
+ENUMX
+  BFD_RELOC_ARM_SWI
+ENUMX
+  BFD_RELOC_ARM_MULTI
+ENUMX
+  BFD_RELOC_ARM_CP_OFF_IMM
+ENUMX
+  BFD_RELOC_ARM_ADR_IMM
+ENUMX
+  BFD_RELOC_ARM_LDR_IMM
+ENUMX
+  BFD_RELOC_ARM_LITERAL
+ENUMX
+  BFD_RELOC_ARM_IN_POOL
+ENUMX
+  BFD_RELOC_ARM_OFFSET_IMM8
+ENUMX
+  BFD_RELOC_ARM_HWLITERAL
+ENUMX
+  BFD_RELOC_ARM_THUMB_ADD
+ENUMX
+  BFD_RELOC_ARM_THUMB_IMM
+ENUMX
+  BFD_RELOC_ARM_THUMB_SHIFT
+ENUMX
+  BFD_RELOC_ARM_THUMB_OFFSET
+ENUMDOC
+  These relocs are only used within the ARM assembler.  They are not
+  (at present) written to any object files.
+
+ENUM
+  BFD_RELOC_SH_PCDISP8BY2
+ENUMX
+  BFD_RELOC_SH_PCDISP12BY2
+ENUMX
+  BFD_RELOC_SH_IMM4
+ENUMX
+  BFD_RELOC_SH_IMM4BY2
+ENUMX
+  BFD_RELOC_SH_IMM4BY4
+ENUMX
+  BFD_RELOC_SH_IMM8
+ENUMX
+  BFD_RELOC_SH_IMM8BY2
+ENUMX
+  BFD_RELOC_SH_IMM8BY4
+ENUMX
+  BFD_RELOC_SH_PCRELIMM8BY2
+ENUMX
+  BFD_RELOC_SH_PCRELIMM8BY4
+ENUMX
+  BFD_RELOC_SH_SWITCH16
+ENUMX
+  BFD_RELOC_SH_SWITCH32
+ENUMX
+  BFD_RELOC_SH_USES
+ENUMX
+  BFD_RELOC_SH_COUNT
+ENUMX
+  BFD_RELOC_SH_ALIGN
+ENUMX
+  BFD_RELOC_SH_CODE
+ENUMX
+  BFD_RELOC_SH_DATA
+ENUMX
+  BFD_RELOC_SH_LABEL
+ENUMDOC
+  Hitachi SH relocs.  Not all of these appear in object files.
+
+ENUM
+  BFD_RELOC_THUMB_PCREL_BRANCH9
+ENUMX
+  BFD_RELOC_THUMB_PCREL_BRANCH12
+ENUMX
+  BFD_RELOC_THUMB_PCREL_BRANCH23
+ENUMDOC
+  Thumb 23-, 12- and 9-bit pc-relative branches.  The lowest bit must
+  be zero and is not stored in the instruction.
+
+ENUM
+  BFD_RELOC_ARC_B22_PCREL
+ENUMDOC
+  Argonaut RISC Core (ARC) relocs.
+  ARC 22 bit pc-relative branch.  The lowest two bits must be zero and are
+  not stored in the instruction.  The high 20 bits are installed in bits 26
+  through 7 of the instruction.
+ENUM
+  BFD_RELOC_ARC_B26
+ENUMDOC
+  ARC 26 bit absolute branch.  The lowest two bits must be zero and are not
+  stored in the instruction.  The high 24 bits are installed in bits 23
+  through 0.
+
+COMMENT
+ENUM
+  BFD_RELOC_D10V_10_PCREL_R
+ENUMDOC
+  Mitsubishi D10V relocs.
+  This is a 10-bit reloc with the right 2 bits
+  assumed to be 0.
+ENUM
+  BFD_RELOC_D10V_10_PCREL_L
+ENUMDOC
+  Mitsubishi D10V relocs.
+  This is a 10-bit reloc with the right 2 bits
+  assumed to be 0.  This is the same as the previous reloc
+  except it is in the left container, i.e.,
+  shifted left 15 bits.
+ENUM
+  BFD_RELOC_D10V_18
+ENUMDOC
+  This is an 18-bit reloc with the right 2 bits
+  assumed to be 0.
+ENUM
+  BFD_RELOC_D10V_18_PCREL
+ENUMDOC
+  This is an 18-bit reloc with the right 2 bits
+  assumed to be 0.
+COMMENT
+
+COMMENT
+{* start-sanitize-d30v *}
+ENUM
+  BFD_RELOC_D30V_6
+ENUMDOC
+  Mitsubishi D30V relocs.
+  This is a 6-bit absolute reloc.
+ENUM
+  BFD_RELOC_D30V_9_PCREL
+ENUMDOC
+  This is a 6-bit pc-relative reloc with 
+  the right 3 bits assumed to be 0.  
+ENUM
+  BFD_RELOC_D30V_9_PCREL_R
+ENUMDOC
+  This is a 6-bit pc-relative reloc with 
+  the right 3 bits assumed to be 0. Same
+  as the previous reloc but on the right side
+  of the container.  
+ENUM
+  BFD_RELOC_D30V_15
+ENUMDOC
+  This is a 12-bit absolute reloc with the 
+  right 3 bitsassumed to be 0.  
+ENUM
+  BFD_RELOC_D30V_15_PCREL
+ENUMDOC
+  This is a 12-bit pc-relative reloc with 
+  the right 3 bits assumed to be 0.  
+ENUM
+  BFD_RELOC_D30V_15_PCREL_R
+ENUMDOC
+  This is a 12-bit pc-relative reloc with 
+  the right 3 bits assumed to be 0. Same
+  as the previous reloc but on the right side
+  of the container.  
+ENUM
+  BFD_RELOC_D30V_21
+ENUMDOC
+  This is an 18-bit absolute reloc with 
+  the right 3 bits assumed to be 0.
+ENUM
+  BFD_RELOC_D30V_21_PCREL
+ENUMDOC
+  This is an 18-bit pc-relative reloc with 
+  the right 3 bits assumed to be 0.
+ENUM
+  BFD_RELOC_D30V_21_PCREL_R
+ENUMDOC
+  This is an 18-bit pc-relative reloc with 
+  the right 3 bits assumed to be 0. Same
+  as the previous reloc but on the right side
+  of the container.
+ENUM
+  BFD_RELOC_D30V_32
+ENUMDOC
+  This is a 32-bit absolute reloc.
+ENUM
+  BFD_RELOC_D30V_32_PCREL
+ENUMDOC
+  This is a 32-bit pc-relative reloc.
+COMMENT
+{* end-sanitize-d30v *}
+
+ENUM
+  BFD_RELOC_M32R_24
+ENUMDOC
+  Mitsubishi M32R relocs.
+  This is a 24 bit absolute address.
+ENUM
+  BFD_RELOC_M32R_10_PCREL
+ENUMDOC
+  This is a 10-bit pc-relative reloc with the right 2 bits assumed to be 0.
+ENUM
+  BFD_RELOC_M32R_18_PCREL
+ENUMDOC
+  This is an 18-bit reloc with the right 2 bits assumed to be 0.
+ENUM
+  BFD_RELOC_M32R_26_PCREL
+ENUMDOC
+  This is a 26-bit reloc with the right 2 bits assumed to be 0.
+ENUM
+  BFD_RELOC_M32R_HI16_ULO
+ENUMDOC
+  This is a 16-bit reloc containing the high 16 bits of an address
+  used when the lower 16 bits are treated as unsigned.
+ENUM
+  BFD_RELOC_M32R_HI16_SLO
+ENUMDOC
+  This is a 16-bit reloc containing the high 16 bits of an address
+  used when the lower 16 bits are treated as signed.
+ENUM
+  BFD_RELOC_M32R_LO16
+ENUMDOC
+  This is a 16-bit reloc containing the lower 16 bits of an address.
+ENUM
+  BFD_RELOC_M32R_SDA16
+ENUMDOC
+  This is a 16-bit reloc containing the small data area offset for use in
+  add3, load, and store instructions.
+
+ENUM
+  BFD_RELOC_V850_9_PCREL
+ENUMDOC
+  This is a 9-bit reloc
+ENUM
+  BFD_RELOC_V850_22_PCREL
+ENUMDOC
+  This is a 22-bit reloc
+
+ENUM
+  BFD_RELOC_V850_SDA_16_16_OFFSET
+ENUMDOC
+  This is a 16 bit offset from the short data area pointer.
+ENUM
+  BFD_RELOC_V850_SDA_15_16_OFFSET
+ENUMDOC
+  This is a 16 bit offset (of which only 15 bits are used) from the
+  short data area pointer.
+ENUM
+  BFD_RELOC_V850_ZDA_16_16_OFFSET
+ENUMDOC
+  This is a 16 bit offset from the zero data area pointer.
+ENUM
+  BFD_RELOC_V850_ZDA_15_16_OFFSET
+ENUMDOC
+  This is a 16 bit offset (of which only 15 bits are used) from the
+  zero data area pointer.
+ENUM
+  BFD_RELOC_V850_TDA_6_8_OFFSET
+ENUMDOC
+  This is an 8 bit offset (of which only 6 bits are used) from the
+  tiny data area pointer.
+ENUM
+  BFD_RELOC_V850_TDA_7_8_OFFSET
+ENUMDOC
+  This is an 8bit offset (of which only 7 bits are used) from the tiny
+  data area pointer.
+ENUM
+  BFD_RELOC_V850_TDA_7_7_OFFSET
+ENUMDOC
+  This is a 7 bit offset from the tiny data area pointer.
+ENUM
+  BFD_RELOC_V850_TDA_16_16_OFFSET
+ENUMDOC
+  This is a 16 bit offset from the tiny data area pointer.
+COMMENT
+{* start-sanitize-v850e *}
+ENUM
+  BFD_RELOC_V850_TDA_4_5_OFFSET
+ENUMDOC
+  This is a 5 bit offset (of which only 4 bits are used) from the tiny
+  data area pointer.
+ENUM
+  BFD_RELOC_V850_TDA_4_4_OFFSET
+ENUMDOC
+  This is a 4 bit offset from the tiny data area pointer.
+ENUM
+  BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET
+ENUMDOC
+  This is a 16 bit offset from the short data area pointer, with the
+  bits placed non-contigously in the instruction.
+ENUM
+  BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET
+ENUMDOC
+  This is a 16 bit offset from the zero data area pointer, with the
+  bits placed non-contigously in the instruction.
+ENUM
+  BFD_RELOC_V850_CALLT_6_7_OFFSET
+ENUMDOC
+  This is a 6 bit offset from the call table base pointer.
+ENUM
+  BFD_RELOC_V850_CALLT_16_16_OFFSET
+ENUMDOC
+  This is a 16 bit offset from the call table base pointer.
+COMMENT
+{* end-sanitize-v850e *}
+
+ENUM
+  BFD_RELOC_MN10300_32_PCREL
+ENUMDOC
+  This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the
+  instruction.
+ENUM
+  BFD_RELOC_MN10300_16_PCREL
+ENUMDOC
+  This is a 16bit pcrel reloc for the mn10300, offset by two bytes in the
+  instruction.
+
+COMMENT
+{* start-sanitize-sky *}
+ENUM
+  BFD_RELOC_TXVU_11_PCREL
+ENUMDOC
+  SKY TXVU Relocations.
+  This is an 11-bit pc relative reloc.  The recorded address is for the
+  lower instruction word.
+COMMENT
+{* end-sanitize-sky *}
+
+ENDSENUM
+  BFD_RELOC_UNUSED
 CODE_FRAGMENT
 .
-.typedef enum bfd_reloc_code_real
-.{
-.  {* Basic absolute relocations *}
-.  BFD_RELOC_64,
-.  BFD_RELOC_32,
-.  BFD_RELOC_26,
-.  BFD_RELOC_16,
-.  BFD_RELOC_14,
-.  BFD_RELOC_8,
-.
-.  {* PC-relative relocations *}
-.  BFD_RELOC_64_PCREL,
-.  BFD_RELOC_32_PCREL,
-.  BFD_RELOC_24_PCREL,    {* used by i960 *}
-.  BFD_RELOC_16_PCREL,
-.  BFD_RELOC_8_PCREL,
-.
-.  {* Linkage-table relative *}
-.  BFD_RELOC_32_BASEREL,
-.  BFD_RELOC_16_BASEREL,
-.  BFD_RELOC_8_BASEREL,
-.
-.  {* The type of reloc used to build a contructor table - at the moment
-.     probably a 32 bit wide abs address, but the cpu can choose. *}
-.  BFD_RELOC_CTOR,
-.
-.  {* 8 bits wide, but used to form an address like 0xffnn *}
-.  BFD_RELOC_8_FFnn,
-.
-.  {* 32-bit pc-relative, shifted right 2 bits (i.e., 30-bit
-.     word displacement, e.g. for SPARC) *}
-.  BFD_RELOC_32_PCREL_S2,
-.  {* signed 16-bit pc-relative, shifted right 2 bits (e.g. for MIPS) *}
-.  BFD_RELOC_16_PCREL_S2,
-.  {* this is used on the Alpha *}
-.  BFD_RELOC_23_PCREL_S2,
-.
-.  {* High 22 bits of 32-bit value, placed into lower 22 bits of
-.     target word; simple reloc.  *}
-.  BFD_RELOC_HI22,
-.  {* Low 10 bits.  *}
-.  BFD_RELOC_LO10,
-.
-.  {* For systems that allocate a Global Pointer register, these are
-.     displacements off that register.  These relocation types are
-.     handled specially, because the value the register will have is
-.     decided relatively late.  *}
-.  BFD_RELOC_GPREL16,
-.  BFD_RELOC_GPREL32,
-.
-.  {* Reloc types used for i960/b.out.  *}
-.  BFD_RELOC_I960_CALLJ,
-.
-.  {* now for the sparc/elf codes *}
-.  BFD_RELOC_NONE,             {* actually used *}
-.  BFD_RELOC_SPARC_WDISP22,
-.  BFD_RELOC_SPARC22,
-.  BFD_RELOC_SPARC13,
-.  BFD_RELOC_SPARC_GOT10,
-.  BFD_RELOC_SPARC_GOT13,
-.  BFD_RELOC_SPARC_GOT22,
-.  BFD_RELOC_SPARC_PC10,
-.  BFD_RELOC_SPARC_PC22,
-.  BFD_RELOC_SPARC_WPLT30,
-.  BFD_RELOC_SPARC_COPY,
-.  BFD_RELOC_SPARC_GLOB_DAT,
-.  BFD_RELOC_SPARC_JMP_SLOT,
-.  BFD_RELOC_SPARC_RELATIVE,
-.  BFD_RELOC_SPARC_UA32,
-.
-.  {* these are a.out specific? *}
-.  BFD_RELOC_SPARC_BASE13,
-.  BFD_RELOC_SPARC_BASE22,
-.
-.  {* some relocations we're using for sparc v9
-.     -- subject to change *}
-.  BFD_RELOC_SPARC_10,
-.  BFD_RELOC_SPARC_11,
-.#define  BFD_RELOC_SPARC_64 BFD_RELOC_64
-.  BFD_RELOC_SPARC_OLO10,
-.  BFD_RELOC_SPARC_HH22,
-.  BFD_RELOC_SPARC_HM10,
-.  BFD_RELOC_SPARC_LM22,
-.  BFD_RELOC_SPARC_PC_HH22,
-.  BFD_RELOC_SPARC_PC_HM10,
-.  BFD_RELOC_SPARC_PC_LM22,
-.  BFD_RELOC_SPARC_WDISP16,
-.  BFD_RELOC_SPARC_WDISP19,
-.  BFD_RELOC_SPARC_GLOB_JMP,
-.  BFD_RELOC_SPARC_LO7,
-.
-.  {* Alpha ECOFF relocations.  Some of these treat the symbol or "addend"
-.     in some special way.  *}
-.  {* For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when
-.     writing; when reading, it will be the absolute section symbol.  The
-.     addend is the displacement in bytes of the "lda" instruction from
-.     the "ldah" instruction (which is at the address of this reloc).  *}
-.  BFD_RELOC_ALPHA_GPDISP_HI16,
-.  {* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as
-.     with GPDISP_HI16 relocs.  The addend is ignored when writing the
-.     relocations out, and is filled in with the file's GP value on
-.     reading, for convenience.  *}
-.  BFD_RELOC_ALPHA_GPDISP_LO16,
-.
-.  {* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference;
-.     the assembler turns it into a LDQ instruction to load the address of
-.     the symbol, and then fills in a register in the real instruction.
-.
-.     The LITERAL reloc, at the LDQ instruction, refers to the .lita
-.     section symbol.  The addend is ignored when writing, but is filled
-.     in with the file's GP value on reading, for convenience, as with the
-.     GPDISP_LO16 reloc.
-.
-.     The LITUSE reloc, on the instruction using the loaded address, gives
-.     information to the linker that it might be able to use to optimize
-.     away some literal section references.  The symbol is ignored (read
-.     as the absolute section symbol), and the "addend" indicates the type
-.     of instruction using the register:
-.              1 - "memory" fmt insn
-.              2 - byte-manipulation (byte offset reg)
-.              3 - jsr (target of branch)
-.
-.     The GNU linker currently doesn't do any of this optimizing.  *}
-.  BFD_RELOC_ALPHA_LITERAL,
-.  BFD_RELOC_ALPHA_LITUSE,
-.
-.  {* The HINT relocation indicates a value that should be filled into the
-.     "hint" field of a jmp/jsr/ret instruction, for possible branch-
-.     prediction logic which may be provided on some processors.  *}
-.  BFD_RELOC_ALPHA_HINT,
-.
-.  {* Bits 27..2 of the relocation address shifted right 2 bits;
-.     simple reloc otherwise.  *}
-.  BFD_RELOC_MIPS_JMP,
-.
-.  {* High 16 bits of 32-bit value; simple reloc.  *}
-.  BFD_RELOC_HI16,
-.  {* High 16 bits of 32-bit value but the low 16 bits will be sign
-.     extended and added to form the final result.  If the low 16
-.     bits form a negative number, we need to add one to the high value
-.     to compensate for the borrow when the low bits are added.  *}
-.  BFD_RELOC_HI16_S,
-.  {* Low 16 bits.  *}
-.  BFD_RELOC_LO16,
-.  {* Like BFD_RELOC_HI16_S, but PC relative.  *}
-.  BFD_RELOC_PCREL_HI16_S,
-.  {* Like BFD_RELOC_LO16, but PC relative.  *}
-.  BFD_RELOC_PCREL_LO16,
-.
-.  {* relocation relative to the global pointer.  *}
-.#define BFD_RELOC_MIPS_GPREL BFD_RELOC_GPREL16
-.
-.  {* Relocation against a MIPS literal section.  *}
-.  BFD_RELOC_MIPS_LITERAL,
-.
-.  {* MIPS ELF relocations.  *}
-.  BFD_RELOC_MIPS_GOT16,
-.  BFD_RELOC_MIPS_CALL16,
-.#define BFD_RELOC_MIPS_GPREL32 BFD_RELOC_GPREL32
-.
-.  {* i386/elf relocations *}
-.  BFD_RELOC_386_GOT32,
-.  BFD_RELOC_386_PLT32,
-.  BFD_RELOC_386_COPY,
-.  BFD_RELOC_386_GLOB_DAT,
-.  BFD_RELOC_386_JUMP_SLOT,
-.  BFD_RELOC_386_RELATIVE,
-.  BFD_RELOC_386_GOTOFF,
-.  BFD_RELOC_386_GOTPC,
-.
-.  {* ns32k relocations *}
-.  BFD_RELOC_NS32K_IMM_8,
-.  BFD_RELOC_NS32K_IMM_16,
-.  BFD_RELOC_NS32K_IMM_32,
-.  BFD_RELOC_NS32K_IMM_8_PCREL,
-.  BFD_RELOC_NS32K_IMM_16_PCREL,
-.  BFD_RELOC_NS32K_IMM_32_PCREL,
-.  BFD_RELOC_NS32K_DISP_8,
-.  BFD_RELOC_NS32K_DISP_16,
-.  BFD_RELOC_NS32K_DISP_32,
-.  BFD_RELOC_NS32K_DISP_8_PCREL,
-.  BFD_RELOC_NS32K_DISP_16_PCREL,
-.  BFD_RELOC_NS32K_DISP_32_PCREL,
-.
-.  {* PowerPC/POWER (RS/6000) relocs.  *}
-.  {* 26 bit relative branch.  Low two bits must be zero.  High 24
-.     bits installed in bits 6 through 29 of instruction.  *}
-.  BFD_RELOC_PPC_B26,
-.  {* 26 bit absolute branch, like BFD_RELOC_PPC_B26 but absolute.  *}
-.  BFD_RELOC_PPC_BA26,
-.  {* 16 bit TOC relative reference.  *}
-.  BFD_RELOC_PPC_TOC16,
-.
-.  {* this must be the highest numeric value *}
-.  BFD_RELOC_UNUSED
-. } bfd_reloc_code_real_type;
+.typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
 */
 
 
@@ -1428,7 +2470,7 @@ FUNCTION
        bfd_reloc_type_lookup
 
 SYNOPSIS
-       const struct reloc_howto_struct *
+       reloc_howto_type *
        bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code);
 
 DESCRIPTION
@@ -1439,7 +2481,7 @@ DESCRIPTION
 */
 
 
-const struct reloc_howto_struct *
+reloc_howto_type *
 bfd_reloc_type_lookup (abfd, code)
      bfd *abfd;
      bfd_reloc_code_real_type code;
@@ -1456,7 +2498,7 @@ INTERNAL_FUNCTION
        bfd_default_reloc_type_lookup
 
 SYNOPSIS
-       const struct reloc_howto_struct *bfd_default_reloc_type_lookup
+       reloc_howto_type *bfd_default_reloc_type_lookup
        (bfd *abfd, bfd_reloc_code_real_type  code);
 
 DESCRIPTION
@@ -1465,7 +2507,7 @@ DESCRIPTION
 
 */
 
-const struct reloc_howto_struct *
+reloc_howto_type *
 bfd_default_reloc_type_lookup (abfd, code)
      bfd *abfd;
      bfd_reloc_code_real_type code;
@@ -1489,9 +2531,29 @@ bfd_default_reloc_type_lookup (abfd, code)
     default:
       BFD_FAIL ();
     }
-  return (const struct reloc_howto_struct *) NULL;
+  return (reloc_howto_type *) NULL;
 }
 
+/*
+FUNCTION
+       bfd_get_reloc_code_name
+
+SYNOPSIS
+       const char *bfd_get_reloc_code_name (bfd_reloc_code_real_type code);
+
+DESCRIPTION
+       Provides a printable name for the supplied relocation code.
+       Useful mainly for printing error messages.
+*/
+
+const char *
+bfd_get_reloc_code_name (code)
+     bfd_reloc_code_real_type code;
+{
+  if (code > BFD_RELOC_UNUSED)
+    return 0;
+  return bfd_reloc_code_real_names[(int)code];
+}
 
 /*
 INTERNAL_FUNCTION
@@ -1561,12 +2623,9 @@ bfd_generic_get_relocated_section_contents (abfd, link_info, link_order, data,
   if (reloc_size < 0)
     goto error_return;
 
-  reloc_vector = (arelent **) malloc (reloc_size);
+  reloc_vector = (arelent **) bfd_malloc ((size_t) reloc_size);
   if (reloc_vector == NULL && reloc_size != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
 
   /* read in the section */
   if (!bfd_get_section_contents (input_bfd,
This page took 0.039783 seconds and 4 git commands to generate.