2012-11-09 Nick Clifton <nickc@redhat.com>
[binutils-gdb.git] / bfd / elf32-rx.c
index 99cffc0e0092f010652a4f605194a4efea2a9f4e..92c046abfae94482e6765afd6c9b2be54e98357e 100644 (file)
@@ -1,5 +1,5 @@
 /* Renesas RX specific support for 32-bit ELF.
-   Copyright (C) 2008, 2009, 2010, 2011
+   Copyright (C) 2008, 2009, 2010, 2011, 2012
    Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -32,6 +32,7 @@
    endian-swap we would otherwise get.  We check for this in
    rx_elf_object_p().  */
 const bfd_target bfd_elf32_rx_be_ns_vec;
+const bfd_target bfd_elf32_rx_be_vec;
 
 #ifdef DEBUG
 char * rx_get_reloc (long);
@@ -520,9 +521,9 @@ rx_elf_relocate_section
          name = h->root.root.string;
        }
 
-      if (sec != NULL && elf_discarded_section (sec))
+      if (sec != NULL && discarded_section (sec))
        RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-                                        rel, relend, howto, contents);
+                                        rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
        {
@@ -1652,7 +1653,7 @@ rx_offset_for_reloc (bfd *                    abfd,
          if (ssec)
            {
              if ((ssec->flags & SEC_MERGE)
-                 && ssec->sec_info_type == ELF_INFO_TYPE_MERGE)
+                 && ssec->sec_info_type == SEC_INFO_TYPE_MERGE)
                symval = _bfd_merged_section_offset (abfd, & ssec,
                                                     elf_section_data (ssec)->sec_info,
                                                     symval);
@@ -1925,14 +1926,14 @@ elf32_rx_relax_section (bfd *                  abfd,
       if (shndx_buf == NULL)
        goto error_return;
       if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-         || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
+         || bfd_bread (shndx_buf, amt, abfd) != amt)
        goto error_return;
       shndx_hdr->contents = (bfd_byte *) shndx_buf;
     }
 
   /* Get a copy of the native relocations.  */
   internal_relocs = (_bfd_elf_link_read_relocs
-                    (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
+                    (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
                      link_info->keep_memory));
   if (internal_relocs == NULL)
     goto error_return;
@@ -2114,7 +2115,7 @@ elf32_rx_relax_section (bfd *                  abfd,
                   /* Decodable bits.  */
                   && (insn[0] & 0xcc) == 0xcc
                   /* Width.  */
-                  && (insn[0] & 0x30) != 3
+                  && (insn[0] & 0x30) != 0x30
                   /* Register MSBs.  */
                   && (insn[1] & 0x88)  == 0x00)
            {
@@ -2218,7 +2219,7 @@ elf32_rx_relax_section (bfd *                  abfd,
                   /* Decodable bits.  */
                   && (insn[0] & 0xc3) == 0xc3
                   /* Width.  */
-                  && (insn[0] & 0x30) != 3
+                  && (insn[0] & 0x30) != 0x30
                   /* Register MSBs.  */
                   && (insn[1] & 0x88)  == 0x00)
            {
@@ -2936,6 +2937,39 @@ bfd_elf32_rx_set_target_flags (bfd_boolean user_no_warn_mismatch,
   ignore_lma = user_ignore_lma;
 }
 
+/* Converts FLAGS into a descriptive string.
+   Returns a static pointer.  */
+
+static const char *
+describe_flags (flagword flags)
+{
+  static char buf [128];
+
+  buf[0] = 0;
+
+  if (flags & E_FLAG_RX_64BIT_DOUBLES)
+    strcat (buf, "64-bit doubles");
+  else
+    strcat (buf, "32-bit doubles");
+
+  if (flags & E_FLAG_RX_DSP)
+    strcat (buf, ", dsp");
+  else
+    strcat (buf, ", no dsp");
+
+  if (flags & E_FLAG_RX_PID)
+    strcat (buf, ", pid");
+  else
+    strcat (buf, ", no pid");
+
+  if (flags & E_FLAG_RX_ABI)
+    strcat (buf, ", RX ABI");
+  else
+    strcat (buf, ", GCC ABI");
+
+  return buf;
+}
+
 /* Merge backend specific data from an object file to the output
    object file when linking.  */
 
@@ -2957,7 +2991,10 @@ rx_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
     }
   else if (old_flags != new_flags)
     {
-      flagword known_flags = E_FLAG_RX_64BIT_DOUBLES | E_FLAG_RX_DSP | E_FLAG_RX_PID;
+      flagword known_flags;
+
+      known_flags = E_FLAG_RX_ABI | E_FLAG_RX_64BIT_DOUBLES
+       | E_FLAG_RX_DSP | E_FLAG_RX_PID;
 
       if ((old_flags ^ new_flags) & known_flags)
        {
@@ -2970,9 +3007,12 @@ rx_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
            }
          else
            {
-             (*_bfd_error_handler)
-               ("ELF header flags mismatch: old_flags = 0x%.8lx, new_flags = 0x%.8lx, filename = %s",
-                old_flags, new_flags, bfd_get_filename (ibfd));
+             _bfd_error_handler ("There is a conflict merging the ELF header flags from %s",
+                                 bfd_get_filename (ibfd));
+             _bfd_error_handler ("  the input  file's flags: %s",
+                                 describe_flags (new_flags));
+             _bfd_error_handler ("  the output file's flags: %s",
+                                 describe_flags (old_flags));
              error = TRUE;
            }
        }
@@ -3000,21 +3040,20 @@ rx_elf_print_private_bfd_data (bfd * abfd, void * ptr)
   flags = elf_elfheader (abfd)->e_flags;
   fprintf (file, _("private flags = 0x%lx:"), (long) flags);
 
-  if (flags & E_FLAG_RX_64BIT_DOUBLES)
-    fprintf (file, _(" [64-bit doubles]"));
-  if (flags & E_FLAG_RX_DSP)
-    fprintf (file, _(" [dsp]"));
-
-  fputc ('\n', file);
+  fprintf (file, describe_flags (flags));
   return TRUE;
 }
 
 /* Return the MACH for an e_flags value.  */
 
 static int
-elf32_rx_machine (bfd * abfd)
+elf32_rx_machine (bfd * abfd ATTRIBUTE_UNUSED)
 {
+#if 0 /* FIXME: EF_RX_CPU_MASK collides with E_FLAG_RX_...
+        Need to sort out how these flag bits are used.
+         For now we assume that the flags are OK.  */
   if ((elf_elfheader (abfd)->e_flags & EF_RX_CPU_MASK) == EF_RX_CPU_RX)
+#endif
     return bfd_mach_rx;
 
   return 0;
@@ -3028,6 +3067,7 @@ rx_elf_object_p (bfd * abfd)
   Elf_Internal_Phdr *phdr = elf_tdata (abfd)->phdr;
   int nphdrs = elf_elfheader (abfd)->e_phnum;
   sec_ptr bsec;
+  static int saw_be = FALSE;
 
   /* We never want to automatically choose the non-swapping big-endian
      target.  The user can only get that explicitly, such as with -I
@@ -3036,6 +3076,15 @@ rx_elf_object_p (bfd * abfd)
       && abfd->target_defaulted)
     return FALSE;
 
+  /* BFD->target_defaulted is not set to TRUE when a target is chosen
+     as a fallback, so we check for "scanning" to know when to stop
+     using the non-swapping target.  */
+  if (abfd->xvec == &bfd_elf32_rx_be_ns_vec
+      && saw_be)
+    return FALSE;
+  if (abfd->xvec == &bfd_elf32_rx_be_vec)
+    saw_be = TRUE;
+
   bfd_default_set_arch_mach (abfd, bfd_arch_rx,
                             elf32_rx_machine (abfd));
 
@@ -3049,7 +3098,8 @@ rx_elf_object_p (bfd * abfd)
        {
          Elf_Internal_Shdr *sec = elf_tdata(abfd)->elf_sect_ptr[u];
 
-         if (phdr[i].p_offset <= (bfd_vma) sec->sh_offset
+         if (phdr[i].p_filesz
+             && phdr[i].p_offset <= (bfd_vma) sec->sh_offset
              && (bfd_vma)sec->sh_offset <= phdr[i].p_offset + (phdr[i].p_filesz - 1))
            {
              /* Found one!  The difference between the two addresses,
@@ -3073,7 +3123,8 @@ rx_elf_object_p (bfd * abfd)
       bsec = abfd->sections;
       while (bsec)
        {
-         if (phdr[i].p_vaddr <= bsec->lma
+         if (phdr[i].p_filesz
+             && phdr[i].p_vaddr <= bsec->vma
              && bsec->vma <= phdr[i].p_vaddr + (phdr[i].p_filesz - 1))
            {
              bsec->lma = phdr[i].p_paddr + (bsec->vma - phdr[i].p_vaddr);
@@ -3482,6 +3533,17 @@ elf32_rx_modify_program_headers (bfd * abfd ATTRIBUTE_UNUSED,
 
   return TRUE;
 }
+
+/* The default literal sections should always be marked as "code" (i.e.,
+   SHF_EXECINSTR).  This is particularly important for big-endian mode
+   when we do not want their contents byte reversed.  */
+static const struct bfd_elf_special_section elf32_rx_special_sections[] =
+{
+  { STRING_COMMA_LEN (".init_array"),    0, SHT_INIT_ARRAY, SHF_ALLOC + SHF_EXECINSTR },
+  { STRING_COMMA_LEN (".fini_array"),    0, SHT_FINI_ARRAY, SHF_ALLOC + SHF_EXECINSTR },
+  { STRING_COMMA_LEN (".preinit_array"), 0, SHT_PREINIT_ARRAY, SHF_ALLOC + SHF_EXECINSTR },
+  { NULL,                        0,      0, 0,            0 }
+};
 \f
 #define ELF_ARCH               bfd_arch_rx
 #define ELF_MACHINE_CODE       EM_RX
@@ -3510,6 +3572,7 @@ elf32_rx_modify_program_headers (bfd * abfd ATTRIBUTE_UNUSED,
 #define bfd_elf32_set_section_contents         rx_set_section_contents
 #define bfd_elf32_bfd_final_link               rx_final_link
 #define bfd_elf32_bfd_relax_section            elf32_rx_relax_section_wrapper
+#define elf_backend_special_sections           elf32_rx_special_sections
 
 #include "elf32-target.h"