]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elf32-crx.c
Re: PR26978, Inconsistency for strong foo@v1 and weak foo@@v1
[thirdparty/binutils-gdb.git] / bfd / elf32-crx.c
index 90948bcfb8595580c682372e85bb1a554317af6e..e7912746be92ab66e903627c7e1a8ca873400b2a 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD back-end for National Semiconductor's CRX ELF
-   Copyright (C) 2004-2015 Free Software Foundation, Inc.
+   Copyright (C) 2004-2024 Free Software Foundation, Inc.
    Written by Tomer Levi, NSC, Israel.
 
    This file is part of BFD, the Binary File Descriptor library.
 
 static reloc_howto_type *elf_crx_reloc_type_lookup
   (bfd *, bfd_reloc_code_real_type);
-static void elf_crx_info_to_howto
+static bool elf_crx_info_to_howto
   (bfd *, arelent *, Elf_Internal_Rela *);
-static bfd_boolean elf32_crx_relax_delete_bytes
+static bool elf32_crx_relax_delete_bytes
   (struct bfd_link_info *, bfd *, asection *, bfd_vma, int);
 static bfd_reloc_status_type crx_elf_final_link_relocate
   (reloc_howto_type *, bfd *, bfd *, asection *,
    bfd_byte *, bfd_vma, bfd_vma, bfd_vma,
    struct bfd_link_info *, asection *, int);
-static bfd_boolean elf32_crx_relocate_section
+static int elf32_crx_relocate_section
   (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
    Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
-static bfd_boolean elf32_crx_relax_section
-  (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
+static bool elf32_crx_relax_section
+  (bfd *, asection *, struct bfd_link_info *, bool *);
 static bfd_byte * elf32_crx_get_relocated_section_contents
   (bfd *, struct bfd_link_info *, struct bfd_link_order *,
-   bfd_byte *, bfd_boolean, asymbol **);
+   bfd_byte *, bool, asymbol **);
 
 /* crx_reloc_map array maps BFD relocation enum into a CRGAS relocation type.  */
 
@@ -82,306 +82,306 @@ static reloc_howto_type crx_elf_howto_table[] =
 {
   HOWTO (R_CRX_NONE,           /* type */
         0,                     /* rightshift */
-        2,                     /* size */
-        32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        0,                     /* size */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_NONE",          /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0,                     /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_REL4,           /* type */
         1,                     /* rightshift */
-        0,                     /* size */
+        1,                     /* size */
         4,                     /* bitsize */
-        TRUE,                  /* pc_relative */
+        true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_REL4",          /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xf,                   /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_REL8,           /* type */
         1,                     /* rightshift */
-        0,                     /* size */
+        1,                     /* size */
         8,                     /* bitsize */
-        TRUE,                  /* pc_relative */
+        true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_REL8",          /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xff,                  /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_REL8_CMP,       /* type */
         1,                     /* rightshift */
-        0,                     /* size */
+        1,                     /* size */
         8,                     /* bitsize */
-        TRUE,                  /* pc_relative */
+        true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_REL8_CMP",      /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xff,                  /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_REL16,          /* type */
         1,                     /* rightshift */
-        1,                     /* size */
+        2,                     /* size */
         16,                    /* bitsize */
-        TRUE,                  /* pc_relative */
+        true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_REL16",         /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_REL24,          /* type */
         1,                     /* rightshift */
-        2,                     /* size */
+        4,                     /* size */
         24,                    /* bitsize */
-        TRUE,                  /* pc_relative */
+        true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_REL24",         /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffffff,              /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_REL32,          /* type */
         1,                     /* rightshift */
-        2,                     /* size */
+        4,                     /* size */
         32,                    /* bitsize */
-        TRUE,                  /* pc_relative */
+        true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_REL32",         /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_REGREL12,       /* type */
         0,                     /* rightshift */
-        1,                     /* size */
+        2,                     /* size */
         12,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_REGREL12",      /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xfff,                 /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_REGREL22,       /* type */
         0,                     /* rightshift */
-        2,                     /* size */
+        4,                     /* size */
         22,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_REGREL22",      /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0x3fffff,              /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_REGREL28,       /* type */
         0,                     /* rightshift */
-        2,                     /* size */
+        4,                     /* size */
         28,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_REGREL28",      /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xfffffff,             /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_REGREL32,       /* type */
         0,                     /* rightshift */
-        2,                     /* size */
+        4,                     /* size */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_REGREL32",      /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_ABS16,          /* type */
         0,                     /* rightshift */
-        1,                     /* size */
+        2,                     /* size */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_ABS16",         /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_ABS32,          /* type */
         0,                     /* rightshift */
-        2,                     /* size */
+        4,                     /* size */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_ABS32",         /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_NUM8,           /* type */
         0,                     /* rightshift */
-        0,                     /* size */
+        1,                     /* size */
         8,                     /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_NUM8",          /* name */
-        FALSE,                 /* partial_inplace */
-        0x0,                   /* src_mask */
+        false,                 /* partial_inplace */
+        0x0,                   /* src_mask */
         0xff,                  /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_NUM16,          /* type */
         0,                     /* rightshift */
-        1,                     /* size */
+        2,                     /* size */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_NUM16",         /* name */
-        FALSE,                 /* partial_inplace */
-        0x0,                   /* src_mask */
+        false,                 /* partial_inplace */
+        0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_NUM32,          /* type */
         0,                     /* rightshift */
-        2,                     /* size */
+        4,                     /* size */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_NUM32",         /* name */
-        FALSE,                 /* partial_inplace */
-        0x0,                   /* src_mask */
+        false,                 /* partial_inplace */
+        0x0,                   /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_IMM16,          /* type */
         0,                     /* rightshift */
-        1,                     /* size */
+        2,                     /* size */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_IMM16",         /* name */
-        FALSE,                 /* partial_inplace */
-        0x0,                   /* src_mask */
+        false,                 /* partial_inplace */
+        0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_CRX_IMM32,          /* type */
         0,                     /* rightshift */
-        2,                     /* size */
+        4,                     /* size */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_IMM32",         /* name */
-        FALSE,                 /* partial_inplace */
-        0x0,                   /* src_mask */
+        false,                 /* partial_inplace */
+        0x0,                   /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* An 8 bit switch table entry.  This is generated for an expression
      such as ``.byte L1 - L2''.  The offset holds the difference
      between the reloc address and L2.  */
   HOWTO (R_CRX_SWITCH8,                /* type */
         0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        1,                     /* size */
         8,                     /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_unsigned, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_SWITCH8",       /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xff,                  /* dst_mask */
-        TRUE),                 /* pcrel_offset */
+        true),                 /* pcrel_offset */
 
   /* A 16 bit switch table entry.  This is generated for an expression
      such as ``.word L1 - L2''.  The offset holds the difference
      between the reloc address and L2.  */
   HOWTO (R_CRX_SWITCH16,       /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_unsigned, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_SWITCH16",      /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        TRUE),                 /* pcrel_offset */
+        true),                 /* pcrel_offset */
 
   /* A 32 bit switch table entry.  This is generated for an expression
      such as ``.long L1 - L2''.  The offset holds the difference
      between the reloc address and L2.  */
   HOWTO (R_CRX_SWITCH32,       /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_unsigned, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRX_SWITCH32",      /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffffffff,            /* dst_mask */
-        TRUE)                  /* pcrel_offset */
+        true)                  /* pcrel_offset */
 };
 
 /* Retrieve a howto ptr using a BFD reloc_code.  */
@@ -418,13 +418,21 @@ elf_crx_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 
 /* Retrieve a howto ptr using an internal relocation entry.  */
 
-static void
-elf_crx_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
+static bool
+elf_crx_info_to_howto (bfd *abfd, arelent *cache_ptr,
                       Elf_Internal_Rela *dst)
 {
   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_CRX_MAX);
+  if (r_type >= R_CRX_MAX)
+    {
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+                         abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      return false;
+    }
   cache_ptr->howto = &crx_elf_howto_table[r_type];
+  return true;
 }
 
 /* Perform a relocation as part of a final link.  */
@@ -498,25 +506,18 @@ crx_elf_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd,
      as signed or unsigned.  */
   check = Rvalue >> howto->rightshift;
 
-  /* Assumes two's complement.  This expression avoids
-     overflow if howto->bitsize is the number of bits in
-     bfd_vma.  */
-  reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
+  reloc_bits = ((bfd_vma) 1 << (howto->bitsize - 1) << 1) - 1;
 
-  if (((bfd_vma) check & ~reloc_bits) != 0
-      && (((bfd_vma) check & ~reloc_bits)
-         != (-(bfd_vma) 1 & ~reloc_bits)))
+  if ((check & ~reloc_bits) != 0
+      && (check & ~reloc_bits) != ((bfd_vma) -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 && (bfd_signed_vma) Rvalue < 0)
        {
-         check |= ((bfd_vma) - 1
-                   & ~((bfd_vma) - 1
-                       >> howto->rightshift));
-         if (((bfd_vma) check & ~reloc_bits)
-             != (-(bfd_vma) 1 & ~reloc_bits))
+         check |= (bfd_vma) -1 & ~((bfd_vma) -1 >> howto->rightshift);
+         if ((check & ~reloc_bits) != ((bfd_vma) -1 & ~reloc_bits))
            return bfd_reloc_overflow;
        }
       else
@@ -524,14 +525,14 @@ crx_elf_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd,
     }
 
   /* Drop unwanted bits from the value we are relocating to.  */
-  Rvalue >>= (bfd_vma) howto->rightshift;
+  Rvalue >>= howto->rightshift;
 
   /* Apply dst_mask to select only relocatable part of the insn.  */
   Rvalue &= howto->dst_mask;
 
-  switch (howto->size)
+  switch (bfd_get_reloc_size (howto))
     {
-     case 0:
+     case 1:
        if (r_type == R_CRX_REL4)
         {
           Rvalue <<= 4;
@@ -541,14 +542,14 @@ crx_elf_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd,
        bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
        break;
 
-     case 1:
+     case 2:
        if (r_type == R_CRX_REGREL12)
         Rvalue |= (bfd_get_16 (input_bfd, hit_data) & 0xf000);
 
        bfd_put_16 (input_bfd, Rvalue, hit_data);
        break;
 
-     case 2:
+     case 4:
        if (r_type == R_CRX_REL24
           || r_type == R_CRX_REGREL22
           || r_type == R_CRX_REGREL28)
@@ -583,7 +584,7 @@ crx_elf_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd,
 
 /* Delete some bytes from a section while relaxing.  */
 
-static bfd_boolean
+static bool
 elf32_crx_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
                              asection *sec, bfd_vma addr, int count)
 {
@@ -709,7 +710,7 @@ elf32_crx_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
        sym_hash->root.u.def.value -= count;
     }
 
-  return TRUE;
+  return true;
 }
 
 /* This is a version of bfd_generic_get_relocated_section_contents
@@ -720,7 +721,7 @@ elf32_crx_get_relocated_section_contents (bfd *output_bfd,
                                          struct bfd_link_info *link_info,
                                          struct bfd_link_order *link_order,
                                          bfd_byte *data,
-                                         bfd_boolean relocatable,
+                                         bool relocatable,
                                          asymbol **symbols)
 {
   Elf_Internal_Shdr *symtab_hdr;
@@ -741,6 +742,13 @@ elf32_crx_get_relocated_section_contents (bfd *output_bfd,
 
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
 
+  bfd_byte *orig_data = data;
+  if (data == NULL)
+    {
+      data = bfd_malloc (input_section->size);
+      if (data == NULL)
+       return NULL;
+    }
   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
          (size_t) input_section->size);
 
@@ -754,7 +762,7 @@ elf32_crx_get_relocated_section_contents (bfd *output_bfd,
 
       internal_relocs = (_bfd_elf_link_read_relocs
                         (input_bfd, input_section, NULL,
-                         (Elf_Internal_Rela *) NULL, FALSE));
+                         (Elf_Internal_Rela *) NULL, false));
       if (internal_relocs == NULL)
        goto error_return;
 
@@ -797,10 +805,8 @@ elf32_crx_get_relocated_section_contents (bfd *output_bfd,
                                     isymbuf, sections))
        goto error_return;
 
-      if (sections != NULL)
-       free (sections);
-      if (isymbuf != NULL
-         && symtab_hdr->contents != (unsigned char *) isymbuf)
+      free (sections);
+      if (symtab_hdr->contents != (unsigned char *) isymbuf)
        free (isymbuf);
       if (elf_section_data (input_section)->relocs != internal_relocs)
        free (internal_relocs);
@@ -809,20 +815,19 @@ elf32_crx_get_relocated_section_contents (bfd *output_bfd,
   return data;
 
  error_return:
-  if (sections != NULL)
-    free (sections);
-  if (isymbuf != NULL
-      && symtab_hdr->contents != (unsigned char *) isymbuf)
+  free (sections);
+  if (symtab_hdr->contents != (unsigned char *) isymbuf)
     free (isymbuf);
-  if (internal_relocs != NULL
-      && elf_section_data (input_section)->relocs != internal_relocs)
+  if (elf_section_data (input_section)->relocs != internal_relocs)
     free (internal_relocs);
+  if (orig_data == NULL)
+    free (data);
   return NULL;
 }
 
 /* Relocate a CRX ELF section.  */
 
-static bfd_boolean
+static int
 elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                            bfd *input_bfd, asection *input_section,
                            bfd_byte *contents, Elf_Internal_Rela *relocs,
@@ -864,7 +869,7 @@ elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        }
       else
        {
-         bfd_boolean unresolved_reloc, warned, ignored;
+         bool unresolved_reloc, warned, ignored;
 
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
                                   r_symndx, symtab_hdr, sym_hashes,
@@ -876,7 +881,7 @@ elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
                                         rel, 1, relend, howto, 0, contents);
 
-      if (info->relocatable)
+      if (bfd_link_relocatable (info))
        continue;
 
       r = crx_elf_final_link_relocate (howto, input_bfd, output_bfd,
@@ -897,24 +902,20 @@ elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
              name = (bfd_elf_string_from_elf_section
                      (input_bfd, symtab_hdr->sh_link, sym->st_name));
              if (name == NULL || *name == '\0')
-               name = bfd_section_name (input_bfd, sec);
+               name = bfd_section_name (sec);
            }
 
          switch (r)
            {
             case bfd_reloc_overflow:
-              if (!((*info->callbacks->reloc_overflow)
-                    (info, (h ? &h->root : NULL), name, howto->name,
-                     (bfd_vma) 0, input_bfd, input_section,
-                     rel->r_offset)))
-                return FALSE;
+              (*info->callbacks->reloc_overflow)
+                (info, (h ? &h->root : NULL), name, howto->name,
+                 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
               break;
 
             case bfd_reloc_undefined:
-              if (!((*info->callbacks->undefined_symbol)
-                    (info, name, input_bfd, input_section,
-                     rel->r_offset, TRUE)))
-                return FALSE;
+              (*info->callbacks->undefined_symbol)
+                (info, name, input_bfd, input_section, rel->r_offset, true);
               break;
 
             case bfd_reloc_outofrange:
@@ -934,16 +935,14 @@ elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
               /* Fall through.  */
 
             common_error:
-              if (!((*info->callbacks->warning)
-                    (info, msg, name, input_bfd, input_section,
-                     rel->r_offset)))
-                return FALSE;
+              (*info->callbacks->warning) (info, msg, name, input_bfd,
+                                           input_section, rel->r_offset);
               break;
            }
        }
     }
 
-  return TRUE;
+  return true;
 }
 
 /* This function handles relaxing for the CRX.
@@ -957,9 +956,9 @@ elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
    Symbol- and reloc-reading infrastructure copied from elf-m10200.c.  */
 
-static bfd_boolean
+static bool
 elf32_crx_relax_section (bfd *abfd, asection *sec,
-                        struct bfd_link_info *link_info, bfd_boolean *again)
+                        struct bfd_link_info *link_info, bool *again)
 {
   Elf_Internal_Shdr *symtab_hdr;
   Elf_Internal_Rela *internal_relocs;
@@ -968,16 +967,17 @@ elf32_crx_relax_section (bfd *abfd, asection *sec,
   Elf_Internal_Sym *isymbuf = NULL;
 
   /* Assume nothing changes.  */
-  *again = FALSE;
+  *again = false;
 
   /* We don't have to do anything for a relocatable link, if
      this section does not have relocs, or if this is not a
      code section.  */
-  if (link_info->relocatable
-      || (sec->flags & SEC_RELOC) == 0
+  if (bfd_link_relocatable (link_info)
       || sec->reloc_count == 0
+      || (sec->flags & SEC_RELOC) == 0
+      || (sec->flags & SEC_HAS_CONTENTS) == 0
       || (sec->flags & SEC_CODE) == 0)
-    return TRUE;
+    return true;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
 
@@ -1120,7 +1120,7 @@ elf32_crx_relax_section (bfd *abfd, asection *sec,
 
              /* That will change things, so, we should relax again.
                 Note that this is not required, and it may be slow.  */
-             *again = TRUE;
+             *again = true;
            }
        }
 
@@ -1165,7 +1165,7 @@ elf32_crx_relax_section (bfd *abfd, asection *sec,
 
              /* That will change things, so, we should relax again.
                 Note that this is not required, and it may be slow.  */
-             *again = TRUE;
+             *again = true;
            }
        }
 
@@ -1217,7 +1217,7 @@ elf32_crx_relax_section (bfd *abfd, asection *sec,
 
              /* That will change things, so, we should relax again.
                 Note that this is not required, and it may be slow.  */
-             *again = TRUE;
+             *again = true;
            }
        }
 
@@ -1258,7 +1258,7 @@ elf32_crx_relax_section (bfd *abfd, asection *sec,
 
              /* That will change things, so, we should relax again.
                 Note that this is not required, and it may be slow.  */
-             *again = TRUE;
+             *again = true;
            }
        }
     }
@@ -1287,24 +1287,20 @@ elf32_crx_relax_section (bfd *abfd, asection *sec,
        }
     }
 
-  if (internal_relocs != NULL
-      && elf_section_data (sec)->relocs != internal_relocs)
+  if (elf_section_data (sec)->relocs != internal_relocs)
     free (internal_relocs);
 
-  return TRUE;
+  return true;
 
  error_return:
-  if (isymbuf != NULL
-      && symtab_hdr->contents != (unsigned char *) isymbuf)
+  if (symtab_hdr->contents != (unsigned char *) isymbuf)
     free (isymbuf);
-  if (contents != NULL
-      && elf_section_data (sec)->this_hdr.contents != contents)
+  if (elf_section_data (sec)->this_hdr.contents != contents)
     free (contents);
-  if (internal_relocs != NULL
-      && elf_section_data (sec)->relocs != internal_relocs)
+  if (elf_section_data (sec)->relocs != internal_relocs)
     free (internal_relocs);
 
-  return FALSE;
+  return false;
 }
 
 /* Definitions for setting CRX target vector.  */
@@ -1319,7 +1315,7 @@ elf32_crx_relax_section (bfd *abfd, asection *sec,
 #define bfd_elf32_bfd_reloc_name_lookup \
                                        elf_crx_reloc_name_lookup
 #define elf_info_to_howto              elf_crx_info_to_howto
-#define elf_info_to_howto_rel          0
+#define elf_info_to_howto_rel          NULL
 #define elf_backend_relocate_section   elf32_crx_relocate_section
 #define bfd_elf32_bfd_relax_section    elf32_crx_relax_section
 #define bfd_elf32_bfd_get_relocated_section_contents \