2011-10-05 Tristan Gingold <gingold@adacore.com>
[deliverable/binutils-gdb.git] / bfd / elf32-rx.c
index 7d9dbc125f7f726e556d5694b323c1794117ef74..f049f6e3390f448eee7090b9a21533f990449991 100644 (file)
@@ -1,5 +1,5 @@
 /* Renesas RX specific support for 32-bit ELF.
-   Copyright (C) 2008, 2009, 2010
+   Copyright (C) 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -20,6 +20,7 @@
 
 #include "sysdep.h"
 #include "bfd.h"
+#include "bfd_stdint.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/rx.h"
 
 #define RX_OPCODE_BIG_ENDIAN 0
 
+/* This is a meta-target that's used only with objcopy, to avoid the
+   endian-swap we would otherwise get.  We check for this in
+   rx_elf_object_p().  */
+const bfd_target bfd_elf32_rx_be_ns_vec;
+
 #ifdef DEBUG
 char * rx_get_reloc (long);
-void dump_symtab (bfd *, void *, void *);
+void rx_dump_symtab (bfd *, void *, void *);
 #endif
 
 #define RXREL(n,sz,bit,shift,complain,pcrel)                                \
@@ -248,9 +254,12 @@ static const struct rx_reloc_map rx_reloc_map [] =
   { BFD_RELOC_RX_RELAX,                R_RX_RH_RELAX },
   { BFD_RELOC_RX_SYM,          R_RX_SYM },
   { BFD_RELOC_RX_OP_SUBTRACT,  R_RX_OPsub },
+  { BFD_RELOC_RX_OP_NEG,       R_RX_OPneg },
   { BFD_RELOC_RX_ABS8,         R_RX_ABS8 },
   { BFD_RELOC_RX_ABS16,                R_RX_ABS16 },
+  { BFD_RELOC_RX_ABS16_REV,    R_RX_ABS16_REV },
   { BFD_RELOC_RX_ABS32,                R_RX_ABS32 },
+  { BFD_RELOC_RX_ABS32_REV,    R_RX_ABS32_REV },
   { BFD_RELOC_RX_ABS16UL,      R_RX_ABS16UL },
   { BFD_RELOC_RX_ABS16UW,      R_RX_ABS16UW },
   { BFD_RELOC_RX_ABS16U,       R_RX_ABS16U }
@@ -502,15 +511,8 @@ rx_elf_relocate_section
        }
 
       if (sec != NULL && elf_discarded_section (sec))
-       {
-         /* For relocs against symbols from removed linkonce sections,
-            or sections discarded by a linker script, we just want the
-            section contents zeroed.  Avoid any special processing.  */
-         _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
-         rel->r_info = 0;
-         rel->r_addend = 0;
-         continue;
-       }
+       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+                                        rel, relend, howto, contents);
 
       if (info->relocatable)
        {
@@ -2858,13 +2860,16 @@ rx_elf_set_private_flags (bfd * abfd, flagword flags)
 }
 
 static bfd_boolean no_warn_mismatch = FALSE;
+static bfd_boolean ignore_lma = TRUE;
 
-void bfd_elf32_rx_set_target_flags (bfd_boolean);
+void bfd_elf32_rx_set_target_flags (bfd_boolean, bfd_boolean);
 
 void
-bfd_elf32_rx_set_target_flags (bfd_boolean user_no_warn_mismatch)
+bfd_elf32_rx_set_target_flags (bfd_boolean user_no_warn_mismatch,
+                              bfd_boolean user_ignore_lma)
 {
   no_warn_mismatch = user_no_warn_mismatch;
+  ignore_lma = user_ignore_lma;
 }
 
 /* Merge backend specific data from an object file to the output
@@ -2954,15 +2959,72 @@ elf32_rx_machine (bfd * abfd)
 static bfd_boolean
 rx_elf_object_p (bfd * abfd)
 {
+  int i;
+  unsigned int u;
+  Elf_Internal_Phdr *phdr = elf_tdata (abfd)->phdr;
+  int nphdrs = elf_elfheader (abfd)->e_phnum;
+  sec_ptr bsec;
+
+  /* We never want to automatically choose the non-swapping big-endian
+     target.  The user can only get that explicitly, such as with -I
+     and objcopy.  */
+  if (abfd->xvec == &bfd_elf32_rx_be_ns_vec
+      && abfd->target_defaulted)
+    return FALSE;
+
   bfd_default_set_arch_mach (abfd, bfd_arch_rx,
                             elf32_rx_machine (abfd));
+
+  /* For each PHDR in the object, we must find some section that
+     corresponds (based on matching file offsets) and use its VMA
+     information to reconstruct the p_vaddr field we clobbered when we
+     wrote it out.  */
+  for (i=0; i<nphdrs; i++)
+    {
+      for (u=0; u<elf_tdata(abfd)->num_elf_sections; u++)
+       {
+         Elf_Internal_Shdr *sec = elf_tdata(abfd)->elf_sect_ptr[u];
+
+         if (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,
+                plus the difference between the two file offsets, is
+                enough information to reconstruct the lma.  */
+
+             /* Example where they aren't:
+                PHDR[1] = lma fffc0100 offset 00002010 size 00000100
+                SEC[6]  = vma 00000050 offset 00002050 size 00000040
+
+                The correct LMA for the section is fffc0140 + (2050-2010).
+             */
+
+             phdr[i].p_vaddr = sec->sh_addr + (sec->sh_offset - phdr[i].p_offset);
+             break;
+           }
+       }
+
+      /* We must update the bfd sections as well, so we don't stop
+        with one match.  */
+      bsec = abfd->sections;
+      while (bsec)
+       {
+         if (phdr[i].p_vaddr <= bsec->lma
+             && bsec->vma <= phdr[i].p_vaddr + (phdr[i].p_filesz - 1))
+           {
+             bsec->lma = phdr[i].p_paddr + (bsec->vma - phdr[i].p_vaddr);
+           }
+         bsec = bsec->next;
+       }
+    }
+
   return TRUE;
 }
  \f
 
 #ifdef DEBUG
 void
-dump_symtab (bfd * abfd, void * internal_syms, void * external_syms)
+rx_dump_symtab (bfd * abfd, void * internal_syms, void * external_syms)
 {
   size_t locsymcount;
   Elf_Internal_Sym * isymbuf;
@@ -3308,13 +3370,12 @@ rx_final_link (bfd * abfd, struct bfd_link_info * info)
 #endif
       if (o->flags & SEC_CODE
          && bfd_big_endian (abfd)
-         && (o->size % 4 || o->rawsize % 4))
+         && o->size % 4)
        {
 #ifdef DJDEBUG
          fprintf (stderr, "adjusting...\n");
 #endif
          o->size += 4 - (o->size % 4);
-         o->rawsize += 4 - (o->rawsize % 4);
        }
     }
 
@@ -3336,22 +3397,24 @@ elf32_rx_modify_program_headers (bfd * abfd ATTRIBUTE_UNUSED,
   phdr = tdata->phdr;
   count = tdata->program_header_size / bed->s->sizeof_phdr;
 
-  for (i = count; i-- != 0; )
-    if (phdr[i].p_type == PT_LOAD)
-      {
-       /* The Renesas tools expect p_paddr to be zero.  However,
-          there is no other way to store the writable data in ROM for
-          startup initialization.  So, we let the linker *think*
-          we're using paddr and vaddr the "usual" way, but at the
-          last minute we move the paddr into the vaddr (which is what
-          the simulator uses) and zero out paddr.  Note that this
-          does not affect the section headers, just the program
-          headers.  We hope.  */
+  if (ignore_lma)
+    for (i = count; i-- != 0;)
+      if (phdr[i].p_type == PT_LOAD)
+       {
+         /* The Renesas tools expect p_paddr to be zero.  However,
+            there is no other way to store the writable data in ROM for
+            startup initialization.  So, we let the linker *think*
+            we're using paddr and vaddr the "usual" way, but at the
+            last minute we move the paddr into the vaddr (which is what
+            the simulator uses) and zero out paddr.  Note that this
+            does not affect the section headers, just the program
+            headers.  We hope.  */
          phdr[i].p_vaddr = phdr[i].p_paddr;
-         /* If we zero out p_paddr, then the LMA in the section table
+#if 0    /* If we zero out p_paddr, then the LMA in the section table
             becomes wrong.  */
-         /*phdr[i].p_paddr = 0;*/
-      }
+         phdr[i].p_paddr = 0;
+#endif
+       }
 
   return TRUE;
 }
@@ -3385,3 +3448,21 @@ elf32_rx_modify_program_headers (bfd * abfd ATTRIBUTE_UNUSED,
 #define bfd_elf32_bfd_relax_section            elf32_rx_relax_section_wrapper
 
 #include "elf32-target.h"
+
+/* We define a second big-endian target that doesn't have the custom
+   section get/set hooks, for times when we want to preserve the
+   pre-swapped .text sections (like objcopy).  */
+
+#undef  TARGET_BIG_SYM
+#define TARGET_BIG_SYM         bfd_elf32_rx_be_ns_vec
+#undef  TARGET_BIG_NAME
+#define TARGET_BIG_NAME                "elf32-rx-be-ns"
+#undef  TARGET_LITTLE_SYM
+
+#undef bfd_elf32_get_section_contents
+#undef bfd_elf32_set_section_contents
+
+#undef elf32_bed
+#define elf32_bed                              elf32_rx_be_ns_bed
+
+#include "elf32-target.h"
This page took 0.028615 seconds and 4 git commands to generate.