]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/reloc.c
2.41 Release sources
[thirdparty/binutils-gdb.git] / bfd / reloc.c
index 68bc8a85c3d84c3b7ca63ad1766a274c493d63dc..fbc67ac72805005ef7fa6da916d91e38456f480b 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD support for handling relocation entries.
-   Copyright (C) 1990-2018 Free Software Foundation, Inc.
+   Copyright (C) 1990-2023 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -51,6 +51,7 @@ SECTION
 #include "bfdlink.h"
 #include "libbfd.h"
 #include "bfdver.h"
+
 /*
 DOCDD
 INODE
@@ -61,8 +62,7 @@ SUBSECTION
 
        This is the structure of a relocation entry:
 
-CODE_FRAGMENT
-.
+EXTERNAL
 .typedef enum bfd_reloc_status
 .{
 .  {* No errors detected.  Note - the value 2 is used so that it
@@ -81,7 +81,7 @@ CODE_FRAGMENT
 .  {* Unsupported relocation size requested.  *}
 .  bfd_reloc_notsupported,
 .
-.  {* Unused.  *}
+.  {* Target specific meaning.  *}
 .  bfd_reloc_other,
 .
 .  {* The symbol to relocate against was undefined.  *}
@@ -94,8 +94,11 @@ CODE_FRAGMENT
 . }
 . bfd_reloc_status_type;
 .
+.typedef const struct reloc_howto_struct reloc_howto_type;
 .
-.typedef struct reloc_cache_entry
+
+CODE_FRAGMENT
+.struct reloc_cache_entry
 .{
 .  {* A pointer into the canonical table of pointers.  *}
 .  struct bfd_symbol **sym_ptr_ptr;
@@ -109,8 +112,7 @@ CODE_FRAGMENT
 .  {* Pointer to how to perform the required relocation.  *}
 .  reloc_howto_type *howto;
 .
-.}
-.arelent;
+.};
 .
 */
 
@@ -249,7 +251,6 @@ SUBSUBSECTION
        performing a relocation.
 
 CODE_FRAGMENT
-.
 .enum complain_overflow
 .{
 .  {* Do not complain on overflow.  *}
@@ -268,7 +269,7 @@ CODE_FRAGMENT
 .     unsigned number.  *}
 .  complain_overflow_unsigned
 .};
-
+.
 */
 
 /*
@@ -279,51 +280,37 @@ SUBSUBSECTION
        information that libbfd needs to know to tie up a back end's data.
 
 CODE_FRAGMENT
-.struct bfd_symbol;            {* Forward declaration.  *}
-.
 .struct reloc_howto_struct
 .{
-.  {*  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
-.      in a coff environment has the type 023 - because that's
-.      what the outside world calls a R_PCRWORD reloc.  *}
+.  {* The type field has mainly a documentary use - the back end can
+.     do what it wants with it, though normally the back end's idea of
+.     an external reloc number is stored in this field.  *}
 .  unsigned int type;
 .
-.  {*  The value the final relocation is shifted right by.  This drops
-.      unwanted data from the relocation.  *}
-.  unsigned int rightshift;
-.
-.  {*  The size of the item to be relocated.  This is *not* a
-.      power-of-two measure.  To get the number of bytes operated
-.      on by a type of relocation, use bfd_get_reloc_size.  *}
-.  int size;
+.  {* The size of the item to be relocated in bytes.  *}
+.  unsigned int size:4;
 .
-.  {*  The number of bits in the item to be relocated.  This is used
-.      when doing overflow checking.  *}
-.  unsigned int bitsize;
+.  {* The number of bits in the field to be relocated.  This is used
+.     when doing overflow checking.  *}
+.  unsigned int bitsize:7;
 .
-.  {*  The relocation is relative to the field being relocated.  *}
-.  bfd_boolean pc_relative;
+.  {* The value the final relocation is shifted right by.  This drops
+.     unwanted data from the relocation.  *}
+.  unsigned int rightshift:6;
 .
-.  {*  The bit position of the reloc value in the destination.
-.      The relocated value is left shifted by this amount.  *}
-.  unsigned int bitpos;
+.  {* The bit position of the reloc value in the destination.
+.     The relocated value is left shifted by this amount.  *}
+.  unsigned int bitpos:6;
 .
 .  {* What type of overflow error should be checked for when
 .     relocating.  *}
-.  enum complain_overflow complain_on_overflow;
+.  ENUM_BITFIELD (complain_overflow) complain_on_overflow:2;
 .
-.  {* If this field is non null, then the supplied function is
-.     called rather than the normal function.  This allows really
-.     strange relocation methods to be accommodated.  *}
-.  bfd_reloc_status_type (*special_function)
-.    (bfd *, arelent *, struct bfd_symbol *, void *, asection *,
-.     bfd *, char **);
+.  {* The relocation value should be negated before applying.  *}
+.  unsigned int negate:1;
 .
-.  {* The textual name of the relocation type.  *}
-.  char *name;
+.  {* The relocation is relative to the item being relocated.  *}
+.  unsigned int pc_relative:1;
 .
 .  {* Some formats record a relocation addend in the section contents
 .     rather than with the relocation.  For ELF formats this is the
@@ -340,29 +327,44 @@ CODE_FRAGMENT
 .     USE_REL targets set this field to TRUE.  Why this is so is peculiar
 .     to each particular target.  For relocs that aren't used in partial
 .     links (e.g. GOT stuff) it doesn't matter what this is set to.  *}
-.  bfd_boolean partial_inplace;
+.  unsigned int partial_inplace:1;
+.
+.  {* When some formats create PC relative instructions, they leave
+.     the value of the pc of the place being relocated in the offset
+.     slot of the instruction, so that a PC relative relocation can
+.     be made just by adding in an ordinary offset (e.g., sun3 a.out).
+.     Some formats leave the displacement part of an instruction
+.     empty (e.g., ELF); this flag signals the fact.  *}
+.  unsigned int pcrel_offset:1;
+.
+.  {* Whether bfd_install_relocation should just install the addend,
+.     or should follow the practice of some older object formats and
+.     install a value including the symbol.  *}
+.  unsigned int install_addend:1;
 .
 .  {* src_mask selects the part of the instruction (or data) to be used
 .     in the relocation sum.  If the target relocations don't have an
 .     addend in the reloc, eg. ELF USE_REL, src_mask will normally equal
 .     dst_mask to extract the addend from the section contents.  If
 .     relocations do have an addend in the reloc, eg. ELF USE_RELA, this
-.     field should be zero.  Non-zero values for ELF USE_RELA targets are
-.     bogus as in those cases the value in the dst_mask part of the
-.     section contents should be treated as garbage.  *}
+.     field should normally be zero.  Non-zero values for ELF USE_RELA
+.     targets should be viewed with suspicion as normally the value in
+.     the dst_mask part of the section contents should be ignored.  *}
 .  bfd_vma src_mask;
 .
 .  {* dst_mask selects which parts of the instruction (or data) are
 .     replaced with a relocated value.  *}
 .  bfd_vma dst_mask;
 .
-.  {* When some formats create PC relative instructions, they leave
-.     the value of the pc of the place being relocated in the offset
-.     slot of the instruction, so that a PC relative relocation can
-.     be made just by adding in an ordinary offset (e.g., sun3 a.out).
-.     Some formats leave the displacement part of an instruction
-.     empty (e.g., ELF); this flag signals the fact.  *}
-.  bfd_boolean pcrel_offset;
+.  {* If this field is non null, then the supplied function is
+.     called rather than the normal function.  This allows really
+.     strange relocation methods to be accommodated.  *}
+.  bfd_reloc_status_type (*special_function)
+.    (bfd *, arelent *, struct bfd_symbol *, void *, asection *,
+.     bfd *, char **);
+.
+.  {* The textual name of the relocation type.  *}
+.  const char *name;
 .};
 .
 */
@@ -372,84 +374,37 @@ FUNCTION
        The HOWTO Macro
 
 DESCRIPTION
-       The HOWTO define is horrible and will go away.
+       The HOWTO macro fills in a reloc_howto_type (a typedef for
+       const struct reloc_howto_struct).
 
-.#define HOWTO(C, R, S, B, P, BI, O, SF, 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
-       moment, we are compatible, so do it this way.
-
-.#define NEWHOWTO(FUNCTION, NAME, SIZE, REL, IN) \
-.  HOWTO (0, 0, SIZE, 0, REL, 0, complain_overflow_dont, FUNCTION, \
-.        NAME, FALSE, 0, 0, IN)
-.
+.#define HOWTO_INSTALL_ADDEND 0
+.#define HOWTO_RSIZE(sz) ((sz) < 0 ? -(sz) : (sz))
+.#define HOWTO(type, right, size, bits, pcrel, left, ovf, func, name,  \
+.              inplace, src_mask, dst_mask, pcrel_off)                 \
+.  { (unsigned) type, HOWTO_RSIZE (size), bits, right, left, ovf,      \
+.    size < 0, pcrel, inplace, pcrel_off, HOWTO_INSTALL_ADDEND,                \
+.    src_mask, dst_mask, func, name }
 
 DESCRIPTION
        This is used to fill in an empty howto entry in an array.
 
 .#define EMPTY_HOWTO(C) \
-.  HOWTO ((C), 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, \
-.        NULL, FALSE, 0, 0, FALSE)
+.  HOWTO ((C), 0, 1, 0, false, 0, complain_overflow_dont, NULL, \
+.        NULL, false, 0, 0, false)
 .
-
-DESCRIPTION
-       Helper routine to turn a symbol into a relocation value.
-
-.#define HOWTO_PREPARE(relocation, symbol)             \
-.  {                                                   \
-.    if (symbol != NULL)                               \
-.      {                                               \
-.       if (bfd_is_com_section (symbol->section))      \
-.         {                                            \
-.           relocation = 0;                            \
-.         }                                            \
-.       else                                           \
-.         {                                            \
-.           relocation = symbol->value;                \
-.         }                                            \
-.      }                                               \
-.  }
+.static inline unsigned int
+.bfd_get_reloc_size (reloc_howto_type *howto)
+.{
+.  return howto->size;
+.}
 .
 */
 
 /*
-FUNCTION
-       bfd_get_reloc_size
-
-SYNOPSIS
-       unsigned int bfd_get_reloc_size (reloc_howto_type *);
-
-DESCRIPTION
-       For a reloc_howto_type that operates on a fixed number of bytes,
-       this returns the number of bytes operated on.
- */
-
-unsigned int
-bfd_get_reloc_size (reloc_howto_type *howto)
-{
-  switch (howto->size)
-    {
-    case 5: return 3;
-    case 0: return 1;
-    case 1: return 2;
-    case 2: return 4;
-    case 3: return 0;
-    case 4: return 8;
-    case 8: return 16;
-    case -1: return 2;
-    case -2: return 4;
-    default: abort ();
-    }
-}
-
-/*
-TYPEDEF
+DEFINITION
        arelent_chain
 
 DESCRIPTION
-
        How relocs are tied together in an <<asection>>:
 
 .typedef struct relent_chain
@@ -461,8 +416,9 @@ DESCRIPTION
 .
 */
 
-/* N_ONES produces N one bits, without overflowing machine arithmetic.  */
-#define N_ONES(n) (((((bfd_vma) 1 << ((n) - 1)) - 1) << 1) | 1)
+/* N_ONES produces N one bits, without undefined behaviour for N
+   between zero and the number of bits in a bfd_vma.  */
+#define N_ONES(n) ((n) == 0 ? 0 : ((bfd_vma) 1 << ((n) - 1) << 1) - 1)
 
 /*
 FUNCTION
@@ -495,6 +451,9 @@ bfd_check_overflow (enum complain_overflow how,
   bfd_vma fieldmask, addrmask, signmask, ss, a;
   bfd_reloc_status_type flag = bfd_reloc_ok;
 
+  if (bitsize == 0)
+    return flag;
+
   /* Note: BITSIZE should always be <= ADDRSIZE, but in case it's not,
      we'll be permissive: extra bits in the field mask will
      automatically extend the address mask for purposes of the
@@ -544,7 +503,7 @@ FUNCTION
        bfd_reloc_offset_in_range
 
 SYNOPSIS
-       bfd_boolean bfd_reloc_offset_in_range
+       bool bfd_reloc_offset_in_range
          (reloc_howto_type *howto,
           bfd *abfd,
           asection *section,
@@ -559,7 +518,7 @@ DESCRIPTION
 /* HOWTO describes a relocation, at offset OCTET.  Return whether the
    relocation field is within SECTION of ABFD.  */
 
-bfd_boolean
+bool
 bfd_reloc_offset_in_range (reloc_howto_type *howto,
                           bfd *abfd,
                           asection *section,
@@ -571,7 +530,97 @@ bfd_reloc_offset_in_range (reloc_howto_type *howto,
   /* The reloc field must be contained entirely within the section.
      Allow zero length fields (marker relocs or NONE relocs where no
      relocation will be performed) at the end of the section.  */
-  return octet <= octet_end && octet + reloc_size <= octet_end;
+  return octet <= octet_end && reloc_size <= octet_end - octet;
+}
+
+/* Read and return the section contents at DATA converted to a host
+   integer (bfd_vma).  The number of bytes read is given by the HOWTO.  */
+
+static bfd_vma
+read_reloc (bfd *abfd, bfd_byte *data, reloc_howto_type *howto)
+{
+  switch (bfd_get_reloc_size (howto))
+    {
+    case 0:
+      break;
+
+    case 1:
+      return bfd_get_8 (abfd, data);
+
+    case 2:
+      return bfd_get_16 (abfd, data);
+
+    case 3:
+      return bfd_get_24 (abfd, data);
+
+    case 4:
+      return bfd_get_32 (abfd, data);
+
+#ifdef BFD64
+    case 8:
+      return bfd_get_64 (abfd, data);
+#endif
+
+    default:
+      abort ();
+    }
+  return 0;
+}
+
+/* Convert VAL to target format and write to DATA.  The number of
+   bytes written is given by the HOWTO.  */
+
+static void
+write_reloc (bfd *abfd, bfd_vma val, bfd_byte *data, reloc_howto_type *howto)
+{
+  switch (bfd_get_reloc_size (howto))
+    {
+    case 0:
+      break;
+
+    case 1:
+      bfd_put_8 (abfd, val, data);
+      break;
+
+    case 2:
+      bfd_put_16 (abfd, val, data);
+      break;
+
+    case 3:
+      bfd_put_24 (abfd, val, data);
+      break;
+
+    case 4:
+      bfd_put_32 (abfd, val, data);
+      break;
+
+#ifdef BFD64
+    case 8:
+      bfd_put_64 (abfd, val, data);
+      break;
+#endif
+
+    default:
+      abort ();
+    }
+}
+
+/* Apply RELOCATION value to target bytes at DATA, according to
+   HOWTO.  */
+
+static void
+apply_reloc (bfd *abfd, bfd_byte *data, reloc_howto_type *howto,
+            bfd_vma relocation)
+{
+  bfd_vma val = read_reloc (abfd, data, howto);
+
+  if (howto->negate)
+    relocation = -relocation;
+
+  val = ((val & ~howto->dst_mask)
+        | (((val & howto->src_mask) + relocation) & howto->dst_mask));
+
+  write_reloc (abfd, val, data, howto);
 }
 
 /*
@@ -661,7 +710,7 @@ bfd_perform_relocation (bfd *abfd,
     return bfd_reloc_undefined;
 
   /* Is the address of the relocation really within the section?  */
-  octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+  octets = reloc_entry->address * bfd_octets_per_byte (abfd, input_section);
   if (!bfd_reloc_offset_in_range (howto, abfd, input_section, octets))
     return bfd_reloc_outofrange;
 
@@ -683,7 +732,14 @@ bfd_perform_relocation (bfd *abfd,
   else
     output_base = reloc_target_output_section->vma;
 
-  relocation += output_base + symbol->section->output_offset;
+  output_base += symbol->section->output_offset;
+
+  /* If symbol addresses are in octets, convert to bytes.  */
+  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+      && (symbol->section->flags & SEC_ELF_OCTETS))
+    output_base *= bfd_octets_per_byte (abfd, input_section);
+
+  relocation += output_base;
 
   /* Add in supplied addend.  */
   relocation += reloc_entry->addend;
@@ -750,9 +806,7 @@ bfd_perform_relocation (bfd *abfd,
          reloc_entry->address += input_section->output_offset;
 
          /* WTF?? */
-         if (abfd->xvec->flavour == bfd_target_coff_flavour
-             && strcmp (abfd->xvec->name, "coff-Intel-little") != 0
-             && strcmp (abfd->xvec->name, "coff-Intel-big") != 0)
+         if (abfd->xvec->flavour == bfd_target_coff_flavour)
            {
              /* For m68k-coff, the addend was being subtracted twice during
                 relocation with -r.  Removing the line below this comment
@@ -913,80 +967,8 @@ space consuming.  For each target:
      =  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)
-    {
-    case 5:
-      {
-       long x = bfd_get_32 (abfd, (bfd_byte *) data + octets);
-       x >>= 8;
-       DOIT (x);
-       bfd_put_16 (abfd, (bfd_vma) (x >> 8), (bfd_byte *) data + octets);
-       bfd_put_8 (abfd, (x & 0xFF), (unsigned char *) data + 2 + octets);
-      }
-      break;
-
-    case 0:
-      {
-       char x = bfd_get_8 (abfd, (char *) data + octets);
-       DOIT (x);
-       bfd_put_8 (abfd, x, (unsigned char *) data + octets);
-      }
-      break;
-
-    case 1:
-      {
-       short x = bfd_get_16 (abfd, (bfd_byte *) data + octets);
-       DOIT (x);
-       bfd_put_16 (abfd, (bfd_vma) x, (unsigned char *) data + octets);
-      }
-      break;
-    case 2:
-      {
-       long x = bfd_get_32 (abfd, (bfd_byte *) data + octets);
-       DOIT (x);
-       bfd_put_32 (abfd, (bfd_vma) x, (bfd_byte *) data + octets);
-      }
-      break;
-    case -2:
-      {
-       long x = bfd_get_32 (abfd, (bfd_byte *) data + octets);
-       relocation = -relocation;
-       DOIT (x);
-       bfd_put_32 (abfd, (bfd_vma) x, (bfd_byte *) data + octets);
-      }
-      break;
-
-    case -1:
-      {
-       long x = bfd_get_16 (abfd, (bfd_byte *) data + octets);
-       relocation = -relocation;
-       DOIT (x);
-       bfd_put_16 (abfd, (bfd_vma) x, (bfd_byte *) data + octets);
-      }
-      break;
-
-    case 3:
-      /* Do nothing */
-      break;
-
-    case 4:
-#ifdef BFD64
-      {
-       bfd_vma x = bfd_get_64 (abfd, (bfd_byte *) data + octets);
-       DOIT (x);
-       bfd_put_64 (abfd, x, (bfd_byte *) data + octets);
-      }
-#else
-      abort ();
-#endif
-      break;
-    default:
-      return bfd_reloc_other;
-    }
-
+  data = (bfd_byte *) data + octets;
+  apply_reloc (abfd, data, howto, relocation);
   return flag;
 }
 
@@ -1042,8 +1024,6 @@ bfd_install_relocation (bfd *abfd,
         reloc_entry->address field might actually be valid for the
         backend concerned.  It is up to the special_function itself
         to call bfd_reloc_offset_in_range if needed.  */
-      /* 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
@@ -1053,317 +1033,95 @@ bfd_install_relocation (bfd *abfd,
        return cont;
     }
 
-  if (bfd_is_abs_section (symbol->section))
-    {
-      reloc_entry->address += input_section->output_offset;
-      return bfd_reloc_ok;
-    }
-
-  /* No need to check for howto != NULL if !bfd_is_abs_section as
-     it will have been checked in `bfd_perform_relocation already'.  */
-
-  /* Is the address of the relocation really within the section?  */
-  octets = reloc_entry->address * bfd_octets_per_byte (abfd);
-  if (!bfd_reloc_offset_in_range (howto, abfd, input_section, octets))
-    return bfd_reloc_outofrange;
-
-  /* Work out which section the relocation is targeted 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)
-    output_base = 0;
+  if (howto->install_addend)
+    relocation = reloc_entry->addend;
   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)
     {
-      /* 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.
+      if (bfd_is_abs_section (symbol->section))
+       return bfd_reloc_ok;
 
-        We start by subtracting the address of the section containing
-        the location.
+      /* Work out which section the relocation is targeted at and the
+        initial relocation command value.  */
 
-        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, ELF.
-        For those targets, pcrel_offset is TRUE.
+      /* Get symbol value.  (Common symbols are special.)  */
+      if (bfd_is_com_section (symbol->section))
+       relocation = 0;
+      else
+       relocation = symbol->value;
 
-        If we are producing relocatable 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.
+      reloc_target_output_section = symbol->section;
 
-        FIXME: This seems logical to me, but for the case of
-        producing relocatable 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.  */
+      /* Convert input-section-relative symbol value to absolute.  */
+      if (! howto->partial_inplace)
+       output_base = 0;
+      else
+       output_base = reloc_target_output_section->vma;
 
-      relocation -=
-       input_section->output_section->vma + input_section->output_offset;
+      /* If symbol addresses are in octets, convert to bytes.  */
+      if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+         && (symbol->section->flags & SEC_ELF_OCTETS))
+       output_base *= bfd_octets_per_byte (abfd, input_section);
 
-      if (howto->pcrel_offset && howto->partial_inplace)
-       relocation -= reloc_entry->address;
-    }
+      relocation += output_base;
 
-  if (! howto->partial_inplace)
-    {
-      /* 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.
+      /* Add in supplied addend.  */
+      relocation += reloc_entry->addend;
 
-        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;
+      /* Here the variable relocation holds the final address of the
+        symbol we are relocating against, plus any addend.  */
 
-      /* WTF?? */
-      if (abfd->xvec->flavour == bfd_target_coff_flavour
-         && strcmp (abfd->xvec->name, "coff-Intel-little") != 0
-         && strcmp (abfd->xvec->name, "coff-Intel-big") != 0)
+      if (howto->pc_relative)
        {
+         relocation -= input_section->vma;
 
-         /* 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
-relocatable 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 relocatable output.  When
-we are producing relocatable output, logically we should do exactly
-what we do when not producing relocatable 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 relocatable 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;
-         /* FIXME: There should be no target specific code here...  */
-         if (strcmp (abfd->xvec->name, "coff-z8k") != 0)
-           reloc_entry->addend = 0;
-       }
-      else
-       {
-         reloc_entry->addend = relocation;
+         if (howto->pcrel_offset && howto->partial_inplace)
+           relocation -= reloc_entry->address;
        }
     }
 
-  /* 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,
-                              bfd_arch_bits_per_address (abfd),
-                              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 + (octets - data_start_offset);
+  if (!howto->partial_inplace)
+    {
+      reloc_entry->addend = relocation;
+      return flag;
+    }
 
-  switch (howto->size)
+  if (!howto->install_addend
+      && abfd->xvec->flavour == bfd_target_coff_flavour)
     {
-    case 0:
-      {
-       char x = bfd_get_8 (abfd, data);
-       DOIT (x);
-       bfd_put_8 (abfd, x, data);
-      }
-      break;
+      /* This is just weird.  We're subtracting out the original
+        addend, so that for COFF the addend is ignored???  */
+      relocation -= reloc_entry->addend;
+      /* FIXME: There should be no target specific code here...  */
+      if (strcmp (abfd->xvec->name, "coff-z8k") != 0)
+       reloc_entry->addend = 0;
+    }
+  else
+    reloc_entry->addend = relocation;
 
-    case 1:
-      {
-       short x = bfd_get_16 (abfd, data);
-       DOIT (x);
-       bfd_put_16 (abfd, (bfd_vma) x, data);
-      }
-      break;
-    case 2:
-      {
-       long x = bfd_get_32 (abfd, data);
-       DOIT (x);
-       bfd_put_32 (abfd, (bfd_vma) x, data);
-      }
-      break;
-    case -2:
-      {
-       long x = bfd_get_32 (abfd, data);
-       relocation = -relocation;
-       DOIT (x);
-       bfd_put_32 (abfd, (bfd_vma) x, data);
-      }
-      break;
+  /* Is the address of the relocation really within the section?  */
+  octets = reloc_entry->address * bfd_octets_per_byte (abfd, input_section);
+  if (!bfd_reloc_offset_in_range (howto, abfd, input_section, octets))
+    return bfd_reloc_outofrange;
 
-    case 3:
-      /* Do nothing */
-      break;
+  /* 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.  */
+  if (howto->complain_on_overflow != complain_overflow_dont)
+    flag = bfd_check_overflow (howto->complain_on_overflow,
+                              howto->bitsize,
+                              howto->rightshift,
+                              bfd_arch_bits_per_address (abfd),
+                              relocation);
 
-    case 4:
-      {
-       bfd_vma x = bfd_get_64 (abfd, data);
-       DOIT (x);
-       bfd_put_64 (abfd, x, data);
-      }
-      break;
-    default:
-      return bfd_reloc_other;
-    }
+  relocation >>= (bfd_vma) howto->rightshift;
+
+  /* Shift everything up to where it's going to be used.  */
+  relocation <<= (bfd_vma) howto->bitpos;
 
+  data = (bfd_byte *) data_start + (octets - data_start_offset);
+  apply_reloc (abfd, data, howto, relocation);
   return flag;
 }
 
@@ -1399,7 +1157,8 @@ _bfd_final_link_relocate (reloc_howto_type *howto,
                          bfd_vma addend)
 {
   bfd_vma relocation;
-  bfd_size_type octets = address * bfd_octets_per_byte (input_bfd);
+  bfd_size_type octets = (address
+                         * bfd_octets_per_byte (input_bfd, input_section));
 
   /* Sanity check the address.  */
   if (!bfd_reloc_offset_in_range (howto, input_bfd, input_section, octets))
@@ -1430,8 +1189,7 @@ _bfd_final_link_relocate (reloc_howto_type *howto,
     }
 
   return _bfd_relocate_contents (howto, input_bfd, relocation,
-                                contents
-                                + address * bfd_octets_per_byte (input_bfd));
+                                contents + octets);
 }
 
 /* Relocate a given location using a given value and howto.  */
@@ -1442,42 +1200,16 @@ _bfd_relocate_contents (reloc_howto_type *howto,
                        bfd_vma relocation,
                        bfd_byte *location)
 {
-  int size;
-  bfd_vma x = 0;
+  bfd_vma x;
   bfd_reloc_status_type flag;
   unsigned int rightshift = howto->rightshift;
   unsigned int bitpos = howto->bitpos;
 
-  /* If the size is negative, negate RELOCATION.  This isn't very
-     general.  */
-  if (howto->size < 0)
+  if (howto->negate)
     relocation = -relocation;
 
   /* Get the value we are going to relocate.  */
-  size = bfd_get_reloc_size (howto);
-  switch (size)
-    {
-    default:
-      abort ();
-    case 0:
-      return bfd_reloc_ok;
-    case 1:
-      x = bfd_get_8 (input_bfd, location);
-      break;
-    case 2:
-      x = bfd_get_16 (input_bfd, location);
-      break;
-    case 4:
-      x = bfd_get_32 (input_bfd, location);
-      break;
-    case 8:
-#ifdef BFD64
-      x = bfd_get_64 (input_bfd, location);
-#else
-      abort ();
-#endif
-      break;
-    }
+  x = read_reloc (input_bfd, location, howto);
 
   /* Check for overflow.  FIXME: We may drop bits during the addition
      which we don't check for.  We must either check at every single
@@ -1583,28 +1315,7 @@ _bfd_relocate_contents (reloc_howto_type *howto,
        | (((x & howto->src_mask) + relocation) & howto->dst_mask));
 
   /* Put the relocated value back in the object file.  */
-  switch (size)
-    {
-    default:
-      abort ();
-    case 1:
-      bfd_put_8 (input_bfd, x, location);
-      break;
-    case 2:
-      bfd_put_16 (input_bfd, x, location);
-      break;
-    case 4:
-      bfd_put_32 (input_bfd, x, location);
-      break;
-    case 8:
-#ifdef BFD64
-      bfd_put_64 (input_bfd, x, location);
-#else
-      abort ();
-#endif
-      break;
-    }
-
+  write_reloc (input_bfd, x, location, howto);
   return flag;
 }
 
@@ -1613,74 +1324,35 @@ _bfd_relocate_contents (reloc_howto_type *howto,
    relocations against discarded symbols, to make ignorable debug or unwind
    information more obvious.  */
 
-void
+bfd_reloc_status_type
 _bfd_clear_contents (reloc_howto_type *howto,
                     bfd *input_bfd,
                     asection *input_section,
-                    bfd_byte *location)
+                    bfd_byte *buf,
+                    bfd_vma off)
 {
-  int size;
-  bfd_vma x = 0;
+  bfd_vma x;
+  bfd_byte *location;
+
+  if (!bfd_reloc_offset_in_range (howto, input_bfd, input_section, off))
+    return bfd_reloc_outofrange;
 
   /* Get the value we are going to relocate.  */
-  size = bfd_get_reloc_size (howto);
-  switch (size)
-    {
-    default:
-      abort ();
-    case 0:
-      return;
-    case 1:
-      x = bfd_get_8 (input_bfd, location);
-      break;
-    case 2:
-      x = bfd_get_16 (input_bfd, location);
-      break;
-    case 4:
-      x = bfd_get_32 (input_bfd, location);
-      break;
-    case 8:
-#ifdef BFD64
-      x = bfd_get_64 (input_bfd, location);
-#else
-      abort ();
-#endif
-      break;
-    }
+  location = buf + off;
+  x = read_reloc (input_bfd, location, howto);
 
   /* Zero out the unwanted bits of X.  */
   x &= ~howto->dst_mask;
 
   /* For a range list, use 1 instead of 0 as placeholder.  0
      would terminate the list, hiding any later entries.  */
-  if (strcmp (bfd_get_section_name (input_bfd, input_section),
-             ".debug_ranges") == 0
+  if (strcmp (bfd_section_name (input_section), ".debug_ranges") == 0
       && (howto->dst_mask & 1) != 0)
     x |= 1;
 
   /* Put the relocated value back in the object file.  */
-  switch (size)
-    {
-    default:
-    case 0:
-      abort ();
-    case 1:
-      bfd_put_8 (input_bfd, x, location);
-      break;
-    case 2:
-      bfd_put_16 (input_bfd, x, location);
-      break;
-    case 4:
-      bfd_put_32 (input_bfd, x, location);
-      break;
-    case 8:
-#ifdef BFD64
-      bfd_put_64 (input_bfd, x, location);
-#else
-      abort ();
-#endif
-      break;
-    }
+  write_reloc (input_bfd, x, location, howto);
+  return bfd_reloc_ok;
 }
 
 /*
@@ -1698,8 +1370,8 @@ SUBSECTION
 */
 
 /*
-TYPEDEF
-       bfd_reloc_code_type
+DEFINITION
+       bfd_reloc_code_real_type
 
 DESCRIPTION
        The insides of a reloc code.  The idea is that, eventually, there
@@ -1750,6 +1422,8 @@ the section containing the relocation.  It depends on the specific target.
 
 ENUM
   BFD_RELOC_32_SECREL
+ENUMX
+  BFD_RELOC_16_SECIDX
 ENUMDOC
   Section relative relocations.  Some targets need this for DWARF2.
 
@@ -2442,7 +2116,7 @@ ENUMX
 ENUMX
   BFD_RELOC_MICROMIPS_SCN_DISP
 ENUMX
-  BFD_RELOC_MIPS_REL16
+  BFD_RELOC_MIPS_16
 ENUMX
   BFD_RELOC_MIPS_RELGOT
 ENUMX
@@ -2865,6 +2539,10 @@ ENUMX
   BFD_RELOC_PPC_BA26
 ENUMX
   BFD_RELOC_PPC_TOC16
+ENUMX
+  BFD_RELOC_PPC_TOC16_LO
+ENUMX
+  BFD_RELOC_PPC_TOC16_HI
 ENUMX
   BFD_RELOC_PPC_B16
 ENUMX
@@ -2957,6 +2635,8 @@ ENUMX
   BFD_RELOC_PPC_16DX_HA
 ENUMX
   BFD_RELOC_PPC_REL16DX_HA
+ENUMX
+  BFD_RELOC_PPC_NEG
 ENUMX
   BFD_RELOC_PPC64_HIGHER
 ENUMX
@@ -3007,10 +2687,60 @@ ENUMX
   BFD_RELOC_PPC64_ADDR16_HIGH
 ENUMX
   BFD_RELOC_PPC64_ADDR16_HIGHA
+ENUMX
+  BFD_RELOC_PPC64_REL16_HIGH
+ENUMX
+  BFD_RELOC_PPC64_REL16_HIGHA
+ENUMX
+  BFD_RELOC_PPC64_REL16_HIGHER
+ENUMX
+  BFD_RELOC_PPC64_REL16_HIGHERA
+ENUMX
+  BFD_RELOC_PPC64_REL16_HIGHEST
+ENUMX
+  BFD_RELOC_PPC64_REL16_HIGHESTA
 ENUMX
   BFD_RELOC_PPC64_ADDR64_LOCAL
 ENUMX
   BFD_RELOC_PPC64_ENTRY
+ENUMX
+  BFD_RELOC_PPC64_REL24_NOTOC
+ENUMX
+  BFD_RELOC_PPC64_REL24_P9NOTOC
+ENUMX
+  BFD_RELOC_PPC64_D34
+ENUMX
+  BFD_RELOC_PPC64_D34_LO
+ENUMX
+  BFD_RELOC_PPC64_D34_HI30
+ENUMX
+  BFD_RELOC_PPC64_D34_HA30
+ENUMX
+  BFD_RELOC_PPC64_PCREL34
+ENUMX
+  BFD_RELOC_PPC64_GOT_PCREL34
+ENUMX
+  BFD_RELOC_PPC64_PLT_PCREL34
+ENUMX
+  BFD_RELOC_PPC64_ADDR16_HIGHER34
+ENUMX
+  BFD_RELOC_PPC64_ADDR16_HIGHERA34
+ENUMX
+  BFD_RELOC_PPC64_ADDR16_HIGHEST34
+ENUMX
+  BFD_RELOC_PPC64_ADDR16_HIGHESTA34
+ENUMX
+  BFD_RELOC_PPC64_REL16_HIGHER34
+ENUMX
+  BFD_RELOC_PPC64_REL16_HIGHERA34
+ENUMX
+  BFD_RELOC_PPC64_REL16_HIGHEST34
+ENUMX
+  BFD_RELOC_PPC64_REL16_HIGHESTA34
+ENUMX
+  BFD_RELOC_PPC64_D28
+ENUMX
+  BFD_RELOC_PPC64_PCREL28
 ENUMDOC
   Power(rs6000) and PowerPC relocations.
 
@@ -3020,6 +2750,14 @@ ENUMX
   BFD_RELOC_PPC_TLSGD
 ENUMX
   BFD_RELOC_PPC_TLSLD
+ENUMX
+  BFD_RELOC_PPC_TLSLE
+ENUMX
+  BFD_RELOC_PPC_TLSIE
+ENUMX
+  BFD_RELOC_PPC_TLSM
+ENUMX
+  BFD_RELOC_PPC_TLSML
 ENUMX
   BFD_RELOC_PPC_DTPMOD
 ENUMX
@@ -3074,10 +2812,26 @@ ENUMX
   BFD_RELOC_PPC_GOT_DTPREL16_HI
 ENUMX
   BFD_RELOC_PPC_GOT_DTPREL16_HA
+ENUMX
+  BFD_RELOC_PPC64_TLSGD
+ENUMX
+  BFD_RELOC_PPC64_TLSLD
+ENUMX
+  BFD_RELOC_PPC64_TLSLE
+ENUMX
+  BFD_RELOC_PPC64_TLSIE
+ENUMX
+  BFD_RELOC_PPC64_TLSM
+ENUMX
+  BFD_RELOC_PPC64_TLSML
 ENUMX
   BFD_RELOC_PPC64_TPREL16_DS
 ENUMX
   BFD_RELOC_PPC64_TPREL16_LO_DS
+ENUMX
+  BFD_RELOC_PPC64_TPREL16_HIGH
+ENUMX
+  BFD_RELOC_PPC64_TPREL16_HIGHA
 ENUMX
   BFD_RELOC_PPC64_TPREL16_HIGHER
 ENUMX
@@ -3090,6 +2844,10 @@ ENUMX
   BFD_RELOC_PPC64_DTPREL16_DS
 ENUMX
   BFD_RELOC_PPC64_DTPREL16_LO_DS
+ENUMX
+  BFD_RELOC_PPC64_DTPREL16_HIGH
+ENUMX
+  BFD_RELOC_PPC64_DTPREL16_HIGHA
 ENUMX
   BFD_RELOC_PPC64_DTPREL16_HIGHER
 ENUMX
@@ -3099,13 +2857,19 @@ ENUMX
 ENUMX
   BFD_RELOC_PPC64_DTPREL16_HIGHESTA
 ENUMX
-  BFD_RELOC_PPC64_TPREL16_HIGH
+  BFD_RELOC_PPC64_TPREL34
 ENUMX
-  BFD_RELOC_PPC64_TPREL16_HIGHA
+  BFD_RELOC_PPC64_DTPREL34
 ENUMX
-  BFD_RELOC_PPC64_DTPREL16_HIGH
+  BFD_RELOC_PPC64_GOT_TLSGD_PCREL34
 ENUMX
-  BFD_RELOC_PPC64_DTPREL16_HIGHA
+  BFD_RELOC_PPC64_GOT_TLSLD_PCREL34
+ENUMX
+  BFD_RELOC_PPC64_GOT_TPREL_PCREL34
+ENUMX
+  BFD_RELOC_PPC64_GOT_DTPREL_PCREL34
+ENUMX
+  BFD_RELOC_PPC64_TLS_PCREL
 ENUMDOC
   PowerPC and PowerPC64 thread-local storage relocations.
 
@@ -3147,6 +2911,36 @@ ENUM
 ENUMDOC
   ARM 26-bit pc-relative branch for B or conditional BL instruction.
 
+ENUM
+  BFD_RELOC_THUMB_PCREL_BRANCH5
+ENUMDOC
+  ARM 5-bit pc-relative branch for Branch Future instructions.
+
+ENUM
+  BFD_RELOC_THUMB_PCREL_BFCSEL
+ENUMDOC
+  ARM 6-bit pc-relative branch for BFCSEL instruction.
+
+ENUM
+  BFD_RELOC_ARM_THUMB_BF17
+ENUMDOC
+  ARM 17-bit pc-relative branch for Branch Future instructions.
+
+ENUM
+  BFD_RELOC_ARM_THUMB_BF13
+ENUMDOC
+  ARM 13-bit pc-relative branch for BFCSEL instruction.
+
+ENUM
+  BFD_RELOC_ARM_THUMB_BF19
+ENUMDOC
+  ARM 19-bit pc-relative branch for Branch Future Link instruction.
+
+ENUM
+  BFD_RELOC_ARM_THUMB_LOOP12
+ENUMDOC
+  ARM 12-bit pc-relative branch for Low Overhead Loop instructions.
+
 ENUM
   BFD_RELOC_THUMB_PCREL_BRANCH7
 ENUMX
@@ -3395,6 +3189,8 @@ ENUMX
   BFD_RELOC_ARM_T32_CP_OFF_IMM
 ENUMX
   BFD_RELOC_ARM_T32_CP_OFF_IMM_S2
+ENUMX
+  BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM
 ENUMX
   BFD_RELOC_ARM_ADR_IMM
 ENUMX
@@ -4393,32 +4189,66 @@ ENUMDOC
   For ex9 and ifc using.
 ENUM
   BFD_RELOC_NDS32_TPOFF
+ENUMX
+  BFD_RELOC_NDS32_GOTTPOFF
 ENUMX
   BFD_RELOC_NDS32_TLS_LE_HI20
 ENUMX
   BFD_RELOC_NDS32_TLS_LE_LO12
+ENUMX
+  BFD_RELOC_NDS32_TLS_LE_20
+ENUMX
+  BFD_RELOC_NDS32_TLS_LE_15S0
+ENUMX
+  BFD_RELOC_NDS32_TLS_LE_15S1
+ENUMX
+  BFD_RELOC_NDS32_TLS_LE_15S2
 ENUMX
   BFD_RELOC_NDS32_TLS_LE_ADD
 ENUMX
   BFD_RELOC_NDS32_TLS_LE_LS
-ENUMX
-  BFD_RELOC_NDS32_GOTTPOFF
 ENUMX
   BFD_RELOC_NDS32_TLS_IE_HI20
+ENUMX
+  BFD_RELOC_NDS32_TLS_IE_LO12
 ENUMX
   BFD_RELOC_NDS32_TLS_IE_LO12S2
 ENUMX
-  BFD_RELOC_NDS32_TLS_TPOFF
+  BFD_RELOC_NDS32_TLS_IEGP_HI20
 ENUMX
-  BFD_RELOC_NDS32_TLS_LE_20
+  BFD_RELOC_NDS32_TLS_IEGP_LO12
 ENUMX
-  BFD_RELOC_NDS32_TLS_LE_15S0
+  BFD_RELOC_NDS32_TLS_IEGP_LO12S2
 ENUMX
-  BFD_RELOC_NDS32_TLS_LE_15S1
+  BFD_RELOC_NDS32_TLS_IEGP_LW
 ENUMX
-  BFD_RELOC_NDS32_TLS_LE_15S2
+  BFD_RELOC_NDS32_TLS_DESC
+ENUMX
+  BFD_RELOC_NDS32_TLS_DESC_HI20
+ENUMX
+  BFD_RELOC_NDS32_TLS_DESC_LO12
+ENUMX
+  BFD_RELOC_NDS32_TLS_DESC_20
+ENUMX
+  BFD_RELOC_NDS32_TLS_DESC_SDA17S2
+ENUMX
+  BFD_RELOC_NDS32_TLS_DESC_ADD
+ENUMX
+  BFD_RELOC_NDS32_TLS_DESC_FUNC
+ENUMX
+  BFD_RELOC_NDS32_TLS_DESC_CALL
+ENUMX
+  BFD_RELOC_NDS32_TLS_DESC_MEM
+ENUMX
+  BFD_RELOC_NDS32_REMOVE
+ENUMX
+  BFD_RELOC_NDS32_GROUP
 ENUMDOC
   For TLS.
+ENUM
+  BFD_RELOC_NDS32_LSI
+ENUMDOC
+  For floating load store relaxation.
 
 
 ENUM
@@ -5218,6 +5048,10 @@ ENUMX
   BFD_RELOC_RISCV_SET32
 ENUMX
   BFD_RELOC_RISCV_32_PCREL
+ENUMX
+  BFD_RELOC_RISCV_SET_ULEB128
+ENUMX
+  BFD_RELOC_RISCV_SUB_ULEB128
 ENUMDOC
   RISC-V relocations.
 
@@ -5956,97 +5790,15 @@ ENUMDOC
 ENUM
   BFD_RELOC_M68HC12_HI8XG
 ENUMDOC
-  Motorola 68HC12/XGATE reloc.
-  This is the 8 bit high part of an absolute address and immediately follows
-  a matching LO8XG part.
-ENUM
-  BFD_RELOC_S12Z_15_PCREL
-ENUMDOC
-  Freescale S12Z reloc.
-  This is a 15 bit relative address.  If the most significant bits are all zero
-  then it may be truncated to 8 bits.
-ENUM
-  BFD_RELOC_16C_NUM08
-ENUMX
-  BFD_RELOC_16C_NUM08_C
-ENUMX
-  BFD_RELOC_16C_NUM16
-ENUMX
-  BFD_RELOC_16C_NUM16_C
-ENUMX
-  BFD_RELOC_16C_NUM32
-ENUMX
-  BFD_RELOC_16C_NUM32_C
-ENUMX
-  BFD_RELOC_16C_DISP04
-ENUMX
-  BFD_RELOC_16C_DISP04_C
-ENUMX
-  BFD_RELOC_16C_DISP08
-ENUMX
-  BFD_RELOC_16C_DISP08_C
-ENUMX
-  BFD_RELOC_16C_DISP16
-ENUMX
-  BFD_RELOC_16C_DISP16_C
-ENUMX
-  BFD_RELOC_16C_DISP24
-ENUMX
-  BFD_RELOC_16C_DISP24_C
-ENUMX
-  BFD_RELOC_16C_DISP24a
-ENUMX
-  BFD_RELOC_16C_DISP24a_C
-ENUMX
-  BFD_RELOC_16C_REG04
-ENUMX
-  BFD_RELOC_16C_REG04_C
-ENUMX
-  BFD_RELOC_16C_REG04a
-ENUMX
-  BFD_RELOC_16C_REG04a_C
-ENUMX
-  BFD_RELOC_16C_REG14
-ENUMX
-  BFD_RELOC_16C_REG14_C
-ENUMX
-  BFD_RELOC_16C_REG16
-ENUMX
-  BFD_RELOC_16C_REG16_C
-ENUMX
-  BFD_RELOC_16C_REG20
-ENUMX
-  BFD_RELOC_16C_REG20_C
-ENUMX
-  BFD_RELOC_16C_ABS20
-ENUMX
-  BFD_RELOC_16C_ABS20_C
-ENUMX
-  BFD_RELOC_16C_ABS24
-ENUMX
-  BFD_RELOC_16C_ABS24_C
-ENUMX
-  BFD_RELOC_16C_IMM04
-ENUMX
-  BFD_RELOC_16C_IMM04_C
-ENUMX
-  BFD_RELOC_16C_IMM16
-ENUMX
-  BFD_RELOC_16C_IMM16_C
-ENUMX
-  BFD_RELOC_16C_IMM20
-ENUMX
-  BFD_RELOC_16C_IMM20_C
-ENUMX
-  BFD_RELOC_16C_IMM24
-ENUMX
-  BFD_RELOC_16C_IMM24_C
-ENUMX
-  BFD_RELOC_16C_IMM32
-ENUMX
-  BFD_RELOC_16C_IMM32_C
+  Motorola 68HC12/XGATE reloc.
+  This is the 8 bit high part of an absolute address and immediately follows
+  a matching LO8XG part.
+ENUM
+  BFD_RELOC_S12Z_15_PCREL
 ENUMDOC
-  NS CR16C Relocations.
+  Freescale S12Z reloc.
+  This is a 15 bit relative address.  If the most significant bits are all zero
+  then it may be truncated to 8 bits.
 
 ENUM
   BFD_RELOC_CR16_NUM8
@@ -6251,18 +6003,32 @@ ENUMDOC
 
 ENUM
   BFD_RELOC_OR1K_REL_26
+ENUMX
+  BFD_RELOC_OR1K_SLO16
+ENUMX
+  BFD_RELOC_OR1K_PCREL_PG21
+ENUMX
+  BFD_RELOC_OR1K_LO13
+ENUMX
+  BFD_RELOC_OR1K_SLO13
 ENUMX
   BFD_RELOC_OR1K_GOTPC_HI16
 ENUMX
   BFD_RELOC_OR1K_GOTPC_LO16
+ENUMX
+  BFD_RELOC_OR1K_GOT_AHI16
 ENUMX
   BFD_RELOC_OR1K_GOT16
+ENUMX
+  BFD_RELOC_OR1K_GOT_PG21
+ENUMX
+  BFD_RELOC_OR1K_GOT_LO13
 ENUMX
   BFD_RELOC_OR1K_PLT26
 ENUMX
-  BFD_RELOC_OR1K_GOTOFF_HI16
+  BFD_RELOC_OR1K_PLTA26
 ENUMX
-  BFD_RELOC_OR1K_GOTOFF_LO16
+  BFD_RELOC_OR1K_GOTOFF_SLO16
 ENUMX
   BFD_RELOC_OR1K_COPY
 ENUMX
@@ -6275,22 +6041,40 @@ ENUMX
   BFD_RELOC_OR1K_TLS_GD_HI16
 ENUMX
   BFD_RELOC_OR1K_TLS_GD_LO16
+ENUMX
+  BFD_RELOC_OR1K_TLS_GD_PG21
+ENUMX
+  BFD_RELOC_OR1K_TLS_GD_LO13
 ENUMX
   BFD_RELOC_OR1K_TLS_LDM_HI16
 ENUMX
   BFD_RELOC_OR1K_TLS_LDM_LO16
+ENUMX
+  BFD_RELOC_OR1K_TLS_LDM_PG21
+ENUMX
+  BFD_RELOC_OR1K_TLS_LDM_LO13
 ENUMX
   BFD_RELOC_OR1K_TLS_LDO_HI16
 ENUMX
   BFD_RELOC_OR1K_TLS_LDO_LO16
 ENUMX
   BFD_RELOC_OR1K_TLS_IE_HI16
+ENUMX
+  BFD_RELOC_OR1K_TLS_IE_AHI16
 ENUMX
   BFD_RELOC_OR1K_TLS_IE_LO16
+ENUMX
+  BFD_RELOC_OR1K_TLS_IE_PG21
+ENUMX
+  BFD_RELOC_OR1K_TLS_IE_LO13
 ENUMX
   BFD_RELOC_OR1K_TLS_LE_HI16
+ENUMX
+  BFD_RELOC_OR1K_TLS_LE_AHI16
 ENUMX
   BFD_RELOC_OR1K_TLS_LE_LO16
+ENUMX
+  BFD_RELOC_OR1K_TLS_LE_SLO16
 ENUMX
   BFD_RELOC_OR1K_TLS_TPOFF
 ENUMX
@@ -6332,17 +6116,6 @@ ENUMDOC
   Self-describing complex relocations.
 COMMENT
 
-ENUM
-  BFD_RELOC_XC16X_PAG
-ENUMX
-  BFD_RELOC_XC16X_POF
-ENUMX
-  BFD_RELOC_XC16X_SEG
-ENUMX
-  BFD_RELOC_XC16X_SOF
-ENUMDOC
-  Infineon Relocations.
-
 ENUM
   BFD_RELOC_VAX_GLOB_DAT
 ENUMX
@@ -6421,6 +6194,11 @@ ENUMX
   BFD_RELOC_MSP430_PREL31
 ENUMX
   BFD_RELOC_MSP430_SYM_DIFF
+ENUMX
+  BFD_RELOC_MSP430_SET_ULEB128
+ENUMX
+  BFD_RELOC_MSP430_SUB_ULEB128
+
 ENUMDOC
   msp430 specific relocation codes
 
@@ -6614,6 +6392,8 @@ ENUMX
 ENUMX
   BFD_RELOC_XTENSA_DIFF32
 ENUMDOC
+  Xtensa relocations for backward compatibility.  These have been replaced
+  by BFD_RELOC_XTENSA_PDIFF and BFD_RELOC_XTENSA_NDIFF.
   Xtensa relocations to mark the difference of two local symbols.
   These are only needed to support linker relaxation and can be ignored
   when not relaxing.  The field is set to the value of the difference
@@ -6726,11 +6506,61 @@ ENUMX
   BFD_RELOC_XTENSA_TLS_CALL
 ENUMDOC
   Xtensa TLS relocations.
+ENUM
+  BFD_RELOC_XTENSA_PDIFF8
+ENUMX
+  BFD_RELOC_XTENSA_PDIFF16
+ENUMX
+  BFD_RELOC_XTENSA_PDIFF32
+ENUMX
+  BFD_RELOC_XTENSA_NDIFF8
+ENUMX
+  BFD_RELOC_XTENSA_NDIFF16
+ENUMX
+  BFD_RELOC_XTENSA_NDIFF32
+ENUMDOC
+  Xtensa relocations to mark the difference of two local symbols.
+  These are only needed to support linker relaxation and can be ignored
+  when not relaxing.  The field is set to the value of the difference
+  assuming no relaxation.  The relocation encodes the position of the
+  subtracted symbol so the linker can determine whether to adjust the field
+  value.  PDIFF relocations are used for positive differences, NDIFF
+  relocations are used for negative differences.  The difference value
+  is treated as unsigned with these relocation types, giving full
+  8/16 value ranges.
 
 ENUM
   BFD_RELOC_Z80_DISP8
 ENUMDOC
   8 bit signed offset in (ix+d) or (iy+d).
+ENUM
+  BFD_RELOC_Z80_BYTE0
+ENUMDOC
+  First 8 bits of multibyte (32, 24 or 16 bit) value.
+ENUM
+  BFD_RELOC_Z80_BYTE1
+ENUMDOC
+  Second 8 bits of multibyte (32, 24 or 16 bit) value.
+ENUM
+  BFD_RELOC_Z80_BYTE2
+ENUMDOC
+  Third 8 bits of multibyte (32 or 24 bit) value.
+ENUM
+  BFD_RELOC_Z80_BYTE3
+ENUMDOC
+  Fourth 8 bits of multibyte (32 bit) value.
+ENUM
+  BFD_RELOC_Z80_WORD0
+ENUMDOC
+  Lowest 16 bits of multibyte (32 or 24 bit) value.
+ENUM
+  BFD_RELOC_Z80_WORD1
+ENUMDOC
+  Highest 16 bits of multibyte (32 or 24 bit) value.
+ENUM
+  BFD_RELOC_Z80_16_BE
+ENUMDOC
+  Like BFD_RELOC_16 but big-endian.
 
 ENUM
   BFD_RELOC_Z8K_DISP7
@@ -7919,6 +7749,13 @@ ENUMX
 ENUMDOC
   Tilera TILE-Gx Relocations.
 
+ENUM
+  BFD_RELOC_BPF_64
+ENUMX
+  BFD_RELOC_BPF_DISP32
+ENUMDOC
+  Linux eBPF relocations.
+
 ENUM
   BFD_RELOC_EPIPHANY_SIMM8
 ENUMDOC
@@ -7988,11 +7825,346 @@ ENUMX
 ENUMDOC
   WebAssembly relocations.
 
+ENUM
+  BFD_RELOC_CKCORE_NONE
+ENUMX
+  BFD_RELOC_CKCORE_ADDR32
+ENUMX
+  BFD_RELOC_CKCORE_PCREL_IMM8BY4
+ENUMX
+  BFD_RELOC_CKCORE_PCREL_IMM11BY2
+ENUMX
+  BFD_RELOC_CKCORE_PCREL_IMM4BY2
+ENUMX
+  BFD_RELOC_CKCORE_PCREL32
+ENUMX
+  BFD_RELOC_CKCORE_PCREL_JSR_IMM11BY2
+ENUMX
+  BFD_RELOC_CKCORE_GNU_VTINHERIT
+ENUMX
+  BFD_RELOC_CKCORE_GNU_VTENTRY
+ENUMX
+  BFD_RELOC_CKCORE_RELATIVE
+ENUMX
+  BFD_RELOC_CKCORE_COPY
+ENUMX
+  BFD_RELOC_CKCORE_GLOB_DAT
+ENUMX
+  BFD_RELOC_CKCORE_JUMP_SLOT
+ENUMX
+  BFD_RELOC_CKCORE_GOTOFF
+ENUMX
+  BFD_RELOC_CKCORE_GOTPC
+ENUMX
+  BFD_RELOC_CKCORE_GOT32
+ENUMX
+  BFD_RELOC_CKCORE_PLT32
+ENUMX
+  BFD_RELOC_CKCORE_ADDRGOT
+ENUMX
+  BFD_RELOC_CKCORE_ADDRPLT
+ENUMX
+  BFD_RELOC_CKCORE_PCREL_IMM26BY2
+ENUMX
+  BFD_RELOC_CKCORE_PCREL_IMM16BY2
+ENUMX
+  BFD_RELOC_CKCORE_PCREL_IMM16BY4
+ENUMX
+  BFD_RELOC_CKCORE_PCREL_IMM10BY2
+ENUMX
+  BFD_RELOC_CKCORE_PCREL_IMM10BY4
+ENUMX
+  BFD_RELOC_CKCORE_ADDR_HI16
+ENUMX
+  BFD_RELOC_CKCORE_ADDR_LO16
+ENUMX
+  BFD_RELOC_CKCORE_GOTPC_HI16
+ENUMX
+  BFD_RELOC_CKCORE_GOTPC_LO16
+ENUMX
+  BFD_RELOC_CKCORE_GOTOFF_HI16
+ENUMX
+  BFD_RELOC_CKCORE_GOTOFF_LO16
+ENUMX
+  BFD_RELOC_CKCORE_GOT12
+ENUMX
+  BFD_RELOC_CKCORE_GOT_HI16
+ENUMX
+  BFD_RELOC_CKCORE_GOT_LO16
+ENUMX
+  BFD_RELOC_CKCORE_PLT12
+ENUMX
+  BFD_RELOC_CKCORE_PLT_HI16
+ENUMX
+  BFD_RELOC_CKCORE_PLT_LO16
+ENUMX
+  BFD_RELOC_CKCORE_ADDRGOT_HI16
+ENUMX
+  BFD_RELOC_CKCORE_ADDRGOT_LO16
+ENUMX
+  BFD_RELOC_CKCORE_ADDRPLT_HI16
+ENUMX
+  BFD_RELOC_CKCORE_ADDRPLT_LO16
+ENUMX
+  BFD_RELOC_CKCORE_PCREL_JSR_IMM26BY2
+ENUMX
+  BFD_RELOC_CKCORE_TOFFSET_LO16
+ENUMX
+  BFD_RELOC_CKCORE_DOFFSET_LO16
+ENUMX
+  BFD_RELOC_CKCORE_PCREL_IMM18BY2
+ENUMX
+  BFD_RELOC_CKCORE_DOFFSET_IMM18
+ENUMX
+  BFD_RELOC_CKCORE_DOFFSET_IMM18BY2
+ENUMX
+  BFD_RELOC_CKCORE_DOFFSET_IMM18BY4
+ENUMX
+  BFD_RELOC_CKCORE_GOTOFF_IMM18
+ENUMX
+  BFD_RELOC_CKCORE_GOT_IMM18BY4
+ENUMX
+  BFD_RELOC_CKCORE_PLT_IMM18BY4
+ENUMX
+  BFD_RELOC_CKCORE_PCREL_IMM7BY4
+ENUMX
+  BFD_RELOC_CKCORE_TLS_LE32
+ENUMX
+  BFD_RELOC_CKCORE_TLS_IE32
+ENUMX
+  BFD_RELOC_CKCORE_TLS_GD32
+ENUMX
+  BFD_RELOC_CKCORE_TLS_LDM32
+ENUMX
+  BFD_RELOC_CKCORE_TLS_LDO32
+ENUMX
+  BFD_RELOC_CKCORE_TLS_DTPMOD32
+ENUMX
+  BFD_RELOC_CKCORE_TLS_DTPOFF32
+ENUMX
+  BFD_RELOC_CKCORE_TLS_TPOFF32
+ENUMX
+  BFD_RELOC_CKCORE_PCREL_FLRW_IMM8BY4
+ENUMX
+  BFD_RELOC_CKCORE_NOJSRI
+ENUMX
+  BFD_RELOC_CKCORE_CALLGRAPH
+ENUMX
+  BFD_RELOC_CKCORE_IRELATIVE
+ENUMX
+  BFD_RELOC_CKCORE_PCREL_BLOOP_IMM4BY4
+ENUMX
+  BFD_RELOC_CKCORE_PCREL_BLOOP_IMM12BY4
+ENUMDOC
+  C-SKY relocations.
+
+ENUM
+  BFD_RELOC_S12Z_OPR
+ENUMDOC
+  S12Z relocations.
+
+ENUM
+  BFD_RELOC_LARCH_TLS_DTPMOD32
+ENUMX
+  BFD_RELOC_LARCH_TLS_DTPREL32
+ENUMX
+  BFD_RELOC_LARCH_TLS_DTPMOD64
+ENUMX
+  BFD_RELOC_LARCH_TLS_DTPREL64
+ENUMX
+  BFD_RELOC_LARCH_TLS_TPREL32
+ENUMX
+  BFD_RELOC_LARCH_TLS_TPREL64
+ENUMX
+  BFD_RELOC_LARCH_MARK_LA
+ENUMX
+  BFD_RELOC_LARCH_MARK_PCREL
+ENUMX
+  BFD_RELOC_LARCH_SOP_PUSH_PCREL
+ENUMX
+  BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE
+ENUMX
+  BFD_RELOC_LARCH_SOP_PUSH_DUP
+ENUMX
+  BFD_RELOC_LARCH_SOP_PUSH_GPREL
+ENUMX
+  BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL
+ENUMX
+  BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT
+ENUMX
+  BFD_RELOC_LARCH_SOP_PUSH_TLS_GD
+ENUMX
+  BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL
+ENUMX
+  BFD_RELOC_LARCH_SOP_ASSERT
+ENUMX
+  BFD_RELOC_LARCH_SOP_NOT
+ENUMX
+  BFD_RELOC_LARCH_SOP_SUB
+ENUMX
+  BFD_RELOC_LARCH_SOP_SL
+ENUMX
+  BFD_RELOC_LARCH_SOP_SR
+ENUMX
+  BFD_RELOC_LARCH_SOP_ADD
+ENUMX
+  BFD_RELOC_LARCH_SOP_AND
+ENUMX
+  BFD_RELOC_LARCH_SOP_IF_ELSE
+ENUMX
+  BFD_RELOC_LARCH_SOP_POP_32_S_10_5
+ENUMX
+  BFD_RELOC_LARCH_SOP_POP_32_U_10_12
+ENUMX
+  BFD_RELOC_LARCH_SOP_POP_32_S_10_12
+ENUMX
+  BFD_RELOC_LARCH_SOP_POP_32_S_10_16
+ENUMX
+  BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2
+ENUMX
+  BFD_RELOC_LARCH_SOP_POP_32_S_5_20
+ENUMX
+  BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2
+ENUMX
+  BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2
+ENUMX
+  BFD_RELOC_LARCH_SOP_POP_32_U
+ENUMX
+  BFD_RELOC_LARCH_ADD8
+ENUMX
+  BFD_RELOC_LARCH_ADD16
+ENUMX
+  BFD_RELOC_LARCH_ADD24
+ENUMX
+  BFD_RELOC_LARCH_ADD32
+ENUMX
+  BFD_RELOC_LARCH_ADD64
+ENUMX
+  BFD_RELOC_LARCH_SUB8
+ENUMX
+  BFD_RELOC_LARCH_SUB16
+ENUMX
+  BFD_RELOC_LARCH_SUB24
+ENUMX
+  BFD_RELOC_LARCH_SUB32
+ENUMX
+  BFD_RELOC_LARCH_SUB64
+
+ENUMX
+  BFD_RELOC_LARCH_B16
+ENUMX
+  BFD_RELOC_LARCH_B21
+ENUMX
+  BFD_RELOC_LARCH_B26
+
+ENUMX
+  BFD_RELOC_LARCH_ABS_HI20
+ENUMX
+  BFD_RELOC_LARCH_ABS_LO12
+ENUMX
+  BFD_RELOC_LARCH_ABS64_LO20
+ENUMX
+  BFD_RELOC_LARCH_ABS64_HI12
+
+ENUMX
+  BFD_RELOC_LARCH_PCALA_HI20
+ENUMX
+  BFD_RELOC_LARCH_PCALA_LO12
+ENUMX
+  BFD_RELOC_LARCH_PCALA64_LO20
+ENUMX
+  BFD_RELOC_LARCH_PCALA64_HI12
+
+ENUMX
+  BFD_RELOC_LARCH_GOT_PC_HI20
+ENUMX
+  BFD_RELOC_LARCH_GOT_PC_LO12
+ENUMX
+  BFD_RELOC_LARCH_GOT64_PC_LO20
+ENUMX
+  BFD_RELOC_LARCH_GOT64_PC_HI12
+ENUMX
+  BFD_RELOC_LARCH_GOT_HI20
+ENUMX
+  BFD_RELOC_LARCH_GOT_LO12
+ENUMX
+  BFD_RELOC_LARCH_GOT64_LO20
+ENUMX
+  BFD_RELOC_LARCH_GOT64_HI12
+
+ENUMX
+  BFD_RELOC_LARCH_TLS_LE_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_LE_LO12
+ENUMX
+  BFD_RELOC_LARCH_TLS_LE64_LO20
+ENUMX
+  BFD_RELOC_LARCH_TLS_LE64_HI12
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE_PC_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE_PC_LO12
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE64_PC_LO20
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE64_PC_HI12
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE_LO12
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE64_LO20
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE64_HI12
+ENUMX
+  BFD_RELOC_LARCH_TLS_LD_PC_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_LD_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_GD_PC_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_GD_HI20
+
+ENUMX
+  BFD_RELOC_LARCH_32_PCREL
+
+ENUMX
+  BFD_RELOC_LARCH_RELAX
+
+ENUMX
+  BFD_RELOC_LARCH_DELETE
+
+ENUMX
+  BFD_RELOC_LARCH_ALIGN
+
+ENUMX
+  BFD_RELOC_LARCH_PCREL20_S2
+
+ENUMX
+  BFD_RELOC_LARCH_CFA
+
+ENUMX
+  BFD_RELOC_LARCH_ADD6
+ENUMX
+  BFD_RELOC_LARCH_SUB6
+
+ENUMX
+  BFD_RELOC_LARCH_ADD_ULEB128
+ENUMX
+  BFD_RELOC_LARCH_SUB_ULEB128
+
+ENUMX
+  BFD_RELOC_LARCH_64_PCREL
+
+ENUMDOC
+  LARCH relocations.
+
 ENDSENUM
   BFD_RELOC_UNUSED
+
 CODE_FRAGMENT
-.
 .typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
+.
 */
 
 /*
@@ -8010,7 +8182,6 @@ DESCRIPTION
        Return a pointer to a howto structure which, when
        invoked, will perform the relocation @var{code} on data from the
        architecture noted.
-
 */
 
 reloc_howto_type *
@@ -8026,7 +8197,7 @@ bfd_reloc_name_lookup (bfd *abfd, const char *reloc_name)
 }
 
 static reloc_howto_type bfd_howto_32 =
-HOWTO (0, 00, 2, 32, FALSE, 0, complain_overflow_dont, 0, "VRT32", FALSE, 0xffffffff, 0xffffffff, TRUE);
+HOWTO (0, 00, 4, 32, false, 0, complain_overflow_dont, 0, "VRT32", false, 0xffffffff, 0xffffffff, true);
 
 /*
 INTERNAL_FUNCTION
@@ -8038,34 +8209,16 @@ SYNOPSIS
 
 DESCRIPTION
        Provides a default relocation lookup routine for any architecture.
-
 */
 
 reloc_howto_type *
 bfd_default_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code)
 {
-  switch (code)
-    {
-    case BFD_RELOC_CTOR:
-      /* The type of reloc used in a ctor, which will be as wide as the
-        address - so either a 64, 32, or 16 bitter.  */
-      switch (bfd_arch_bits_per_address (abfd))
-       {
-       case 64:
-         BFD_FAIL ();
-         break;
-       case 32:
-         return &bfd_howto_32;
-       case 16:
-         BFD_FAIL ();
-         break;
-       default:
-         BFD_FAIL ();
-       }
-      break;
-    default:
-      BFD_FAIL ();
-    }
+  /* Very limited support is provided for relocs in generic targets
+     such as elf32-little.  FIXME: Should we always return NULL?  */
+  if (code == BFD_RELOC_CTOR
+      && bfd_arch_bits_per_address (abfd) == 32)
+    return &bfd_howto_32;
   return NULL;
 }
 
@@ -8094,29 +8247,29 @@ INTERNAL_FUNCTION
        bfd_generic_relax_section
 
 SYNOPSIS
-       bfd_boolean bfd_generic_relax_section
+       bool bfd_generic_relax_section
          (bfd *abfd,
           asection *section,
           struct bfd_link_info *,
-          bfd_boolean *);
+          bool *);
 
 DESCRIPTION
        Provides default handling for relaxing for back ends which
        don't do relaxing.
 */
 
-bfd_boolean
+bool
 bfd_generic_relax_section (bfd *abfd ATTRIBUTE_UNUSED,
                           asection *section ATTRIBUTE_UNUSED,
                           struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
-                          bfd_boolean *again)
+                          bool *again)
 {
   if (bfd_link_relocatable (link_info))
     (*link_info->callbacks->einfo)
       (_("%P%F: --relax and -r may not be used together\n"));
 
-  *again = FALSE;
-  return TRUE;
+  *again = false;
+  return true;
 }
 
 /*
@@ -8124,7 +8277,7 @@ INTERNAL_FUNCTION
        bfd_generic_gc_sections
 
 SYNOPSIS
-       bfd_boolean bfd_generic_gc_sections
+       bool bfd_generic_gc_sections
          (bfd *, struct bfd_link_info *);
 
 DESCRIPTION
@@ -8132,11 +8285,11 @@ DESCRIPTION
        don't do section gc -- i.e., does nothing.
 */
 
-bfd_boolean
+bool
 bfd_generic_gc_sections (bfd *abfd ATTRIBUTE_UNUSED,
                         struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
-  return TRUE;
+  return true;
 }
 
 /*
@@ -8144,7 +8297,7 @@ INTERNAL_FUNCTION
        bfd_generic_lookup_section_flags
 
 SYNOPSIS
-       bfd_boolean bfd_generic_lookup_section_flags
+       bool bfd_generic_lookup_section_flags
          (struct bfd_link_info *, struct flag_info *, asection *);
 
 DESCRIPTION
@@ -8153,7 +8306,7 @@ DESCRIPTION
        Returns FALSE if the section should be omitted, otherwise TRUE.
 */
 
-bfd_boolean
+bool
 bfd_generic_lookup_section_flags (struct bfd_link_info *info ATTRIBUTE_UNUSED,
                                  struct flag_info *flaginfo,
                                  asection *section ATTRIBUTE_UNUSED)
@@ -8161,9 +8314,9 @@ bfd_generic_lookup_section_flags (struct bfd_link_info *info ATTRIBUTE_UNUSED,
   if (flaginfo != NULL)
     {
       _bfd_error_handler (_("INPUT_SECTION_FLAGS are not supported"));
-      return FALSE;
+      return false;
     }
-  return TRUE;
+  return true;
 }
 
 /*
@@ -8171,7 +8324,7 @@ INTERNAL_FUNCTION
        bfd_generic_merge_sections
 
 SYNOPSIS
-       bfd_boolean bfd_generic_merge_sections
+       bool bfd_generic_merge_sections
          (bfd *, struct bfd_link_info *);
 
 DESCRIPTION
@@ -8179,11 +8332,11 @@ DESCRIPTION
        which don't have SEC_MERGE support -- i.e., does nothing.
 */
 
-bfd_boolean
+bool
 bfd_generic_merge_sections (bfd *abfd ATTRIBUTE_UNUSED,
                            struct bfd_link_info *link_info ATTRIBUTE_UNUSED)
 {
-  return TRUE;
+  return true;
 }
 
 /*
@@ -8196,13 +8349,12 @@ SYNOPSIS
           struct bfd_link_info *link_info,
           struct bfd_link_order *link_order,
           bfd_byte *data,
-          bfd_boolean relocatable,
+          bool relocatable,
           asymbol **symbols);
 
 DESCRIPTION
        Provides default handling of relocation effort for back ends
        which can't be bothered to do it efficiently.
-
 */
 
 bfd_byte *
@@ -8210,7 +8362,7 @@ bfd_generic_get_relocated_section_contents (bfd *abfd,
                                            struct bfd_link_info *link_info,
                                            struct bfd_link_order *link_order,
                                            bfd_byte *data,
-                                           bfd_boolean relocatable,
+                                           bool relocatable,
                                            asymbol **symbols)
 {
   bfd *input_bfd = link_order->u.indirect.section->owner;
@@ -8224,6 +8376,7 @@ bfd_generic_get_relocated_section_contents (bfd *abfd,
     return NULL;
 
   /* Read in the section.  */
+  bfd_byte *orig_data = data;
   if (!bfd_get_full_section_contents (input_bfd, input_section, &data))
     return NULL;
 
@@ -8235,7 +8388,7 @@ bfd_generic_get_relocated_section_contents (bfd *abfd,
 
   reloc_vector = (arelent **) bfd_malloc (reloc_size);
   if (reloc_vector == NULL)
-    return NULL;
+    goto error_return;
 
   reloc_count = bfd_canonicalize_reloc (input_bfd,
                                        input_section,
@@ -8266,16 +8419,28 @@ bfd_generic_get_relocated_section_contents (bfd *abfd,
              goto error_return;
            }
 
-         if (symbol->section && discarded_section (symbol->section))
+         /* Zap reloc field when the symbol is from a discarded
+            section, ignoring any addend.  Do the same when called
+            from bfd_simple_get_relocated_section_contents for
+            undefined symbols in debug sections.  This is to keep
+            debug info reasonably sane, in particular so that
+            DW_FORM_ref_addr to another file's .debug_info isn't
+            confused with an offset into the current file's
+            .debug_info.  */
+         if ((symbol->section != NULL && discarded_section (symbol->section))
+             || (symbol->section == bfd_und_section_ptr
+                 && (input_section->flags & SEC_DEBUGGING) != 0
+                 && link_info->input_bfds == link_info->output_bfd))
            {
-             bfd_byte *p;
+             bfd_vma off;
              static reloc_howto_type none_howto
-               = HOWTO (0, 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL,
-                        "unused", FALSE, 0, 0, FALSE);
+               = HOWTO (0, 0, 0, 0, false, 0, complain_overflow_dont, NULL,
+                        "unused", false, 0, 0, false);
 
-             p = data + (*parent)->address * bfd_octets_per_byte (input_bfd);
-             _bfd_clear_contents ((*parent)->howto, input_bfd, input_section,
-                                  p);
+             off = ((*parent)->address
+                    * bfd_octets_per_byte (input_bfd, input_section));
+             _bfd_clear_contents ((*parent)->howto, input_bfd,
+                                  input_section, data, off);
              (*parent)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
              (*parent)->addend = 0;
              (*parent)->howto = &none_howto;
@@ -8305,7 +8470,7 @@ bfd_generic_get_relocated_section_contents (bfd *abfd,
                case bfd_reloc_undefined:
                  (*link_info->callbacks->undefined_symbol)
                    (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
-                    input_bfd, input_section, (*parent)->address, TRUE);
+                    input_bfd, input_section, (*parent)->address, true);
                  break;
                case bfd_reloc_dangerous:
                  BFD_ASSERT (error_message != NULL);
@@ -8358,8 +8523,10 @@ bfd_generic_get_relocated_section_contents (bfd *abfd,
   free (reloc_vector);
   return data;
 
-error_return:
+ error_return:
   free (reloc_vector);
+  if (orig_data == NULL)
+    free (data);
   return NULL;
 }
 
@@ -8386,6 +8553,10 @@ _bfd_generic_set_reloc (bfd *abfd ATTRIBUTE_UNUSED,
 {
   section->orelocation = relptr;
   section->reloc_count = count;
+  if (count != 0)
+    section->flags |= SEC_RELOC;
+  else
+    section->flags &= ~SEC_RELOC;
 }
 
 /*
@@ -8393,7 +8564,7 @@ INTERNAL_FUNCTION
        _bfd_unrecognized_reloc
 
 SYNOPSIS
-       bfd_boolean _bfd_unrecognized_reloc
+       bool _bfd_unrecognized_reloc
          (bfd * abfd,
           sec_ptr section,
           unsigned int r_type);
@@ -8404,7 +8575,7 @@ DESCRIPTION
        Returns FALSE so that it can be called from a return statement.
 */
 
-bfd_boolean
+bool
 _bfd_unrecognized_reloc (bfd * abfd, sec_ptr section, unsigned int r_type)
 {
    /* xgettext:c-format */
@@ -8416,7 +8587,7 @@ _bfd_unrecognized_reloc (bfd * abfd, sec_ptr section, unsigned int r_type)
                      BFD_VERSION_STRING);
 
   bfd_set_error (bfd_error_bad_value);
-  return FALSE;
+  return false;
 }
 
 reloc_howto_type *