Add comma after HIGH3ADJ
[deliverable/binutils-gdb.git] / bfd / elf32-xtensa.c
index 67ff80c4ef9b7b8d1da9910354eae44cce86c56c..2cafb3ed104b96a7769e3e6274674fed080a0a44 100644 (file)
 #include "bfd.h"
 #include "sysdep.h"
 
-#ifdef ANSI_PROTOTYPES
 #include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
 #include <strings.h>
 
 #include "bfdlink.h"
@@ -40,7 +36,7 @@
 /* Local helper functions.  */
 
 static bfd_boolean add_extra_plt_sections (bfd *, int);
-static char *build_encoding_error_message (xtensa_opcode, bfd_vma);
+static char *vsprint_msg (const char *, const char *, int, ...) ATTRIBUTE_PRINTF(2,4);
 static bfd_reloc_status_type bfd_elf_xtensa_reloc
   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
 static bfd_boolean do_fix_for_relocatable_link
@@ -1409,7 +1405,6 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   for (s = dynobj->sections; s != NULL; s = s->next)
     {
       const char *name;
-      bfd_boolean strip;
 
       if ((s->flags & SEC_LINKER_CREATED) == 0)
        continue;
@@ -1418,37 +1413,23 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
         of the dynobj section names depend upon the input files.  */
       name = bfd_get_section_name (dynobj, s);
 
-      strip = FALSE;
-
       if (strncmp (name, ".rela", 5) == 0)
        {
-         if (strcmp (name, ".rela.plt") == 0)
-           relplt = TRUE;
-         else if (strcmp (name, ".rela.got") == 0)
-           relgot = TRUE;
-
-         /* We use the reloc_count field as a counter if we need
-            to copy relocs into the output file.  */
-         s->reloc_count = 0;
-       }
-      else if (strncmp (name, ".plt.", 5) == 0
-              || strncmp (name, ".got.plt.", 9) == 0)
-       {
-         if (s->size == 0)
+         if (s->size != 0)
            {
-             /* If we don't need this section, strip it from the output
-                file.  We must create the ".plt*" and ".got.plt*"
-                sections in create_dynamic_sections and/or check_relocs
-                based on a conservative estimate of the PLT relocation
-                count, because the sections must be created before the
-                linker maps input sections to output sections.  The
-                linker does that before size_dynamic_sections, where we
-                compute the exact size of the PLT, so there may be more
-                of these sections than are actually needed.  */
-             strip = TRUE;
+             if (strcmp (name, ".rela.plt") == 0)
+               relplt = TRUE;
+             else if (strcmp (name, ".rela.got") == 0)
+               relgot = TRUE;
+
+             /* We use the reloc_count field as a counter if we need
+                to copy relocs into the output file.  */
+             s->reloc_count = 0;
            }
        }
-      else if (strcmp (name, ".got") != 0
+      else if (strncmp (name, ".plt.", 5) != 0
+              && strncmp (name, ".got.plt.", 9) != 0
+              && strcmp (name, ".got") != 0
               && strcmp (name, ".plt") != 0
               && strcmp (name, ".got.plt") != 0
               && strcmp (name, ".xt.lit.plt") != 0
@@ -1458,13 +1439,24 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
          continue;
        }
 
-      if (strip)
-       s->flags |= SEC_EXCLUDE;
-      else
+      if (s->size == 0)
+       {
+         /* If we don't need this section, strip it from the output
+            file.  We must create the ".plt*" and ".got.plt*"
+            sections in create_dynamic_sections and/or check_relocs
+            based on a conservative estimate of the PLT relocation
+            count, because the sections must be created before the
+            linker maps input sections to output sections.  The
+            linker does that before size_dynamic_sections, where we
+            compute the exact size of the PLT, so there may be more
+            of these sections than are actually needed.  */
+         s->flags |= SEC_EXCLUDE;
+       }
+      else if ((s->flags & SEC_HAS_CONTENTS) != 0)
        {
          /* Allocate memory for the section contents.  */
          s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
-         if (s->contents == NULL && s->size != 0)
+         if (s->contents == NULL)
            return FALSE;
        }
     }
@@ -1750,7 +1742,30 @@ elf_xtensa_do_reloc (reloc_howto_type *howto,
       || xtensa_operand_set_field (isa, opcode, opnd, fmt, slot,
                                   sbuff, newval))
     {
-      *error_message = build_encoding_error_message (opcode, relocation);
+      const char *opname = xtensa_opcode_name (isa, opcode);
+      const char *msg;
+
+      msg = "cannot encode";
+      if (is_direct_call_opcode (opcode))
+       {
+         if ((relocation & 0x3) != 0)
+           msg = "misaligned call target";
+         else
+           msg = "call target out of range";
+       }
+      else if (opcode == get_l32r_opcode ())
+       {
+         if ((relocation & 0x3) != 0)
+           msg = "misaligned literal target";
+         else if (is_alt_relocation (howto->type))
+           msg = "literal target out of range (too many literals)";
+         else if (self_address > relocation)
+           msg = "literal target out of range (try using text-section-literals)";
+         else
+           msg = "literal placed after use";
+       }
+
+      *error_message = vsprint_msg (opname, ": %s", strlen (msg) + 2, msg);
       return bfd_reloc_dangerous;
     }
 
@@ -1775,7 +1790,7 @@ elf_xtensa_do_reloc (reloc_howto_type *howto,
 }
 
 
-static char * ATTRIBUTE_PRINTF(2,4)
+static char *
 vsprint_msg (const char *origmsg, const char *fmt, int arglen, ...)
 {
   /* To reduce the size of the memory leak,
@@ -1805,32 +1820,6 @@ vsprint_msg (const char *origmsg, const char *fmt, int arglen, ...)
 }
 
 
-static char *
-build_encoding_error_message (xtensa_opcode opcode, bfd_vma target_address)
-{
-  const char *opname = xtensa_opcode_name (xtensa_default_isa, opcode);
-  const char *msg;
-
-  msg = "cannot encode";
-  if (is_direct_call_opcode (opcode))
-    {
-      if ((target_address & 0x3) != 0)
-       msg = "misaligned call target";
-      else
-       msg = "call target out of range";
-    }
-  else if (opcode == get_l32r_opcode ())
-    {
-      if ((target_address & 0x3) != 0)
-       msg = "misaligned literal target";
-      else
-       msg = "literal target out of range";
-    }
-
-  return vsprint_msg (opname, ": %s", strlen (msg) + 2, msg);
-}
-
-
 /* This function is registered as the "special_function" in the
    Xtensa howto for handling simplify operations.
    bfd_perform_relocation / bfd_install_relocation use it to
@@ -1938,7 +1927,8 @@ bfd_elf_xtensa_reloc (bfd *abfd,
        *error_message = "";
       *error_message = vsprint_msg (*error_message, ": (%s + 0x%lx)",
                                    strlen (symbol->name) + 17,
-                                   symbol->name, reloc_entry->addend);
+                                   symbol->name,
+                                   (unsigned long) reloc_entry->addend);
     }
 
   return flag;
@@ -2318,10 +2308,11 @@ elf_xtensa_relocate_section (bfd *output_bfd,
          && !((input_section->flags & SEC_DEBUGGING) != 0
               && h->def_dynamic))
        (*_bfd_error_handler)
-         (_("%B(%A+0x%lx): unresolvable relocation against symbol `%s'"),
+         (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
           input_bfd,
           input_section,
           (long) rel->r_offset,
+          howto->name,
           h->root.root.string);
 
       /* There's no point in calling bfd_perform_relocation here.
@@ -4765,6 +4756,19 @@ offset_with_removed_text (text_action_list *action_list, bfd_vma offset)
 }
 
 
+static unsigned
+action_list_count (text_action_list *action_list)
+{
+  text_action *r = action_list->head;
+  unsigned count = 0;
+  for (r = action_list->head; r != NULL; r = r->next)
+    {
+      count++;
+    }
+  return count;
+}
+
+
 static bfd_vma
 offset_with_removed_text_before_fill (text_action_list *action_list,
                                      bfd_vma offset)
@@ -6860,6 +6864,160 @@ compute_ebb_actions (ebb_constraint *ebb_table)
 }
 
 
+/* The xlate_map is a sorted array of address mappings designed to
+   answer the offset_with_removed_text() query with a binary search instead
+   of a linear search through the section's action_list.  */
+
+typedef struct xlate_map_entry xlate_map_entry_t;
+typedef struct xlate_map xlate_map_t;
+
+struct xlate_map_entry
+{
+  unsigned orig_address;
+  unsigned new_address;
+  unsigned size;
+};
+
+struct xlate_map
+{
+  unsigned entry_count;
+  xlate_map_entry_t *entry;
+};
+
+
+static int 
+xlate_compare (const void *a_v, const void *b_v)
+{
+  const xlate_map_entry_t *a = (const xlate_map_entry_t *) a_v;
+  const xlate_map_entry_t *b = (const xlate_map_entry_t *) b_v;
+  if (a->orig_address < b->orig_address)
+    return -1;
+  if (a->orig_address > (b->orig_address + b->size - 1))
+    return 1;
+  return 0;
+}
+
+
+static bfd_vma
+xlate_offset_with_removed_text (const xlate_map_t *map,
+                               text_action_list *action_list,
+                               bfd_vma offset)
+{
+  xlate_map_entry_t tmp;
+  void *r;
+  xlate_map_entry_t *e;
+
+  if (map == NULL)
+    return offset_with_removed_text (action_list, offset);
+
+  if (map->entry_count == 0)
+    return offset;
+
+  tmp.orig_address = offset;
+  tmp.new_address = offset;
+  tmp.size = 1;
+
+  r = bsearch (&offset, map->entry, map->entry_count,
+              sizeof (xlate_map_entry_t), &xlate_compare);
+  e = (xlate_map_entry_t *) r;
+  
+  BFD_ASSERT (e != NULL);
+  if (e == NULL)
+    return offset;
+  return e->new_address - e->orig_address + offset;
+}
+
+
+/* Build a binary searchable offset translation map from a section's
+   action list.  */
+
+static xlate_map_t *
+build_xlate_map (asection *sec, xtensa_relax_info *relax_info)
+{
+  xlate_map_t *map = (xlate_map_t *) bfd_malloc (sizeof (xlate_map_t));
+  text_action_list *action_list = &relax_info->action_list;
+  unsigned num_actions = 0;
+  text_action *r;
+  int removed;
+  xlate_map_entry_t *current_entry;
+
+  if (map == NULL)
+    return NULL;
+
+  num_actions = action_list_count (action_list);
+  map->entry = (xlate_map_entry_t *) 
+    bfd_malloc (sizeof (xlate_map_entry_t) * (num_actions + 1));
+  if (map->entry == NULL)
+    {
+      free (map);
+      return NULL;
+    }
+  map->entry_count = 0;
+  
+  removed = 0;
+  current_entry = &map->entry[0];
+
+  current_entry->orig_address = 0;
+  current_entry->new_address = 0;
+  current_entry->size = 0;
+
+  for (r = action_list->head; r != NULL; r = r->next)
+    {
+      unsigned orig_size = 0;
+      switch (r->action)
+       {
+       case ta_none:
+       case ta_remove_insn:
+       case ta_convert_longcall:
+       case ta_remove_literal:
+       case ta_add_literal:
+         break;
+       case ta_remove_longcall:
+         orig_size = 6;
+         break;
+       case ta_narrow_insn:
+         orig_size = 3;
+         break;
+       case ta_widen_insn:
+         orig_size = 2;
+         break;
+       case ta_fill:
+         break;
+       }
+      current_entry->size =
+       r->offset + orig_size - current_entry->orig_address;
+      if (current_entry->size != 0)
+       {
+         current_entry++;
+         map->entry_count++;
+       }
+      current_entry->orig_address = r->offset + orig_size;
+      removed += r->removed_bytes;
+      current_entry->new_address = r->offset + orig_size - removed;
+      current_entry->size = 0;
+    }
+
+  current_entry->size = (bfd_get_section_limit (sec->owner, sec)
+                        - current_entry->orig_address);
+  if (current_entry->size != 0)
+    map->entry_count++;
+
+  return map;
+}
+
+
+/* Free an offset translation map.  */
+
+static void 
+free_xlate_map (xlate_map_t *map)
+{
+  if (map && map->entry)
+    free (map->entry);
+  if (map)
+    free (map);
+}
+
+
 /* Use check_section_ebb_pcrels_fit to make sure that all of the
    relocations in a section will fit if a proposed set of actions
    are performed.  */
@@ -6873,10 +7031,19 @@ check_section_ebb_pcrels_fit (bfd *abfd,
 {
   unsigned i, j;
   Elf_Internal_Rela *irel;
+  xlate_map_t *xmap = NULL;
+  bfd_boolean ok = TRUE;
   xtensa_relax_info *relax_info;
 
   relax_info = get_xtensa_relax_info (sec);
 
+  if (relax_info && sec->reloc_count > 100)
+    {
+      xmap = build_xlate_map (sec, relax_info);
+      /* NULL indicates out of memory, but the slow version
+        can still be used.  */
+    }
+
   for (i = 0; i < sec->reloc_count; i++)
     {
       r_reloc r_rel;
@@ -6912,10 +7079,12 @@ check_section_ebb_pcrels_fit (bfd *abfd,
 
       if (relax_info)
        {
-         self_offset = offset_with_removed_text (&relax_info->action_list,
-                                                 orig_self_offset);
-         target_offset = offset_with_removed_text (&relax_info->action_list,
-                                                   orig_target_offset);
+         self_offset =
+           xlate_offset_with_removed_text (xmap, &relax_info->action_list,
+                                           orig_self_offset);
+         target_offset =
+           xlate_offset_with_removed_text (xmap, &relax_info->action_list,
+                                           orig_target_offset);
        }
 
       self_removed_bytes = 0;
@@ -6951,18 +7120,30 @@ check_section_ebb_pcrels_fit (bfd *abfd,
 
          opcode = get_relocation_opcode (abfd, sec, contents, irel);
          if (opcode == XTENSA_UNDEFINED)
-           return FALSE;
+           {
+             ok = FALSE;
+             break;
+           }
 
          opnum = get_relocation_opnd (opcode, ELF32_R_TYPE (irel->r_info));
          if (opnum == XTENSA_UNDEFINED)
-           return FALSE;
+           {
+             ok = FALSE;
+             break;
+           }
 
          if (!pcrel_reloc_fits (opcode, opnum, self_offset, target_offset))
-           return FALSE;
+           {
+             ok = FALSE;
+             break;
+           }
        }
     }
 
-  return TRUE;
+  if (xmap)
+    free_xlate_map (xmap);
+
+  return ok;
 }
 
 
@@ -7471,6 +7652,11 @@ relocations_reach (source_reloc *reloc,
          != sec->output_section)
        return FALSE;
 
+      /* Absolute literals in the same output section can always be
+        combined.  */
+      if (reloc[i].is_abs_literal)
+       continue;
+
       /* A literal with no PC-relative relocations can be moved anywhere.  */
       if (reloc[i].opnd != -1)
        {
@@ -9497,14 +9683,8 @@ static const struct bfd_elf_special_section elf_xtensa_special_sections[] =
 #define TARGET_BIG_NAME                        "elf32-xtensa-be"
 #define ELF_ARCH                       bfd_arch_xtensa
 
-/* The new EM_XTENSA value will be recognized beginning in the Xtensa T1040
-   release. However, we still have to generate files with the EM_XTENSA_OLD
-   value so that pre-T1040 tools can read the files.  As soon as we stop
-   caring about pre-T1040 tools, the following two values should be
-   swapped. At the same time, any other code that uses EM_XTENSA_OLD
-   should be changed to use EM_XTENSA.  */
-#define ELF_MACHINE_CODE               EM_XTENSA_OLD
-#define ELF_MACHINE_ALT1               EM_XTENSA
+#define ELF_MACHINE_CODE               EM_XTENSA
+#define ELF_MACHINE_ALT1               EM_XTENSA_OLD
 
 #if XCHAL_HAVE_MMU
 #define ELF_MAXPAGESIZE                        (1 << XCHAL_MMU_MIN_PTE_PAGE_SIZE)
This page took 0.029895 seconds and 4 git commands to generate.