gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / bfd / elf32-arc.c
index 69d8f6e97cbfc267bc7fed570b47504607af8708..06ee60ac409760286d98b6b9febf32260a9866f2 100644 (file)
@@ -1,5 +1,5 @@
 /* ARC-specific support for 32-bit ELF
-   Copyright (C) 1994-2018 Free Software Foundation, Inc.
+   Copyright (C) 1994-2020 Free Software Foundation, Inc.
    Contributed by Cupertino Miranda (cmiranda@synopsys.com).
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -71,16 +71,6 @@ name_for_global_symbol (struct elf_link_hash_entry *h)
       }                                                                        \
   }
 
-
-/* The default symbols representing the init and fini dyn values.
-   TODO: Check what is the relation of those strings with arclinux.em
-   and DT_INIT.  */
-#define INIT_SYM_STRING "_init"
-#define FINI_SYM_STRING "_fini"
-
-char * init_str = INIT_SYM_STRING;
-char * fini_str = FINI_SYM_STRING;
-
 #define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
       case VALUE: \
        return "R_" #TYPE; \
@@ -91,11 +81,11 @@ reloc_type_to_name (unsigned int type)
 {
   switch (type)
     {
-      #include "elf/arc-reloc.def"
+#include "elf/arc-reloc.def"
 
-      default:
-       return "UNKNOWN";
-       break;
+    default:
+      return "UNKNOWN";
+      break;
     }
 }
 
@@ -106,6 +96,35 @@ reloc_type_to_name (unsigned int type)
 
 #define USE_REL 1
 
+/* Similar with bfd_get_32 but taking into account the
+   middle-endianess of the ARC CPUs.  Only to be used in code
+   sections.  */
+
+static bfd_vma
+bfd_get_32_me (bfd * abfd,const unsigned char * data)
+{
+  bfd_vma value = 0;
+
+  if (bfd_big_endian (abfd))
+    value = bfd_get_32 (abfd, data);
+  else
+    {
+      value = ((bfd_get_8 (abfd, data) & 255) << 16);
+      value |= ((bfd_get_8 (abfd, data + 1) & 255) << 24);
+      value |= (bfd_get_8 (abfd, data + 2) & 255);
+      value |= ((bfd_get_8 (abfd, data + 3) & 255) << 8);
+    }
+
+  return value;
+}
+
+static void
+bfd_put_32_me (bfd *abfd, bfd_vma value,unsigned char *data)
+{
+  bfd_put_16 (abfd, (value & 0xffff0000) >> 16, data);
+  bfd_put_16 (abfd, value & 0xffff, data + 2);
+}
+
 static ATTRIBUTE_UNUSED bfd_boolean
 is_reloc_PC_relative (reloc_howto_type *howto)
 {
@@ -165,9 +184,6 @@ struct elf_arc_link_hash_entry
 {
   struct elf_link_hash_entry root;
 
-  /* Track dynamic relocs copied for this symbol.  */
-  struct elf_dyn_relocs *dyn_relocs;
-
   struct got_entry *got_ents;
 };
 
@@ -321,7 +337,6 @@ elf_arc_link_hash_newfunc (struct bfd_hash_entry *entry,
                                     table, string));
   if (ret != NULL)
     {
-      ret->dyn_relocs = NULL;
       ret->got_ents = NULL;
     }
 
@@ -881,7 +896,7 @@ arc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
 
       for (sec = ibfd->sections; sec != NULL; sec = sec->next)
        {
-         if ((bfd_get_section_flags (ibfd, sec)
+         if ((bfd_section_flags (sec)
               & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
              == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
            only_data_sections = FALSE;
@@ -986,22 +1001,22 @@ arc_elf_object_p (bfd * abfd)
     {
       switch (arch)
        {
-         case E_ARC_MACH_ARC600:
-           mach = bfd_mach_arc_arc600;
-           break;
-         case E_ARC_MACH_ARC601:
-           mach = bfd_mach_arc_arc601;
-           break;
-         case E_ARC_MACH_ARC700:
-           mach = bfd_mach_arc_arc700;
-           break;
-         case EF_ARC_CPU_ARCV2HS:
-         case EF_ARC_CPU_ARCV2EM:
-           mach = bfd_mach_arc_arcv2;
-           break;
-         default:
-           mach = bfd_arc_get_mach_from_attributes (abfd);
-           break;
+       case E_ARC_MACH_ARC600:
+         mach = bfd_mach_arc_arc600;
+         break;
+       case E_ARC_MACH_ARC601:
+         mach = bfd_mach_arc_arc601;
+         break;
+       case E_ARC_MACH_ARC700:
+         mach = bfd_mach_arc_arc700;
+         break;
+       case EF_ARC_CPU_ARCV2HS:
+       case EF_ARC_CPU_ARCV2EM:
+         mach = bfd_mach_arc_arcv2;
+         break;
+       default:
+         mach = bfd_arc_get_mach_from_attributes (abfd);
+         break;
        }
     }
   else
@@ -1026,9 +1041,8 @@ arc_elf_object_p (bfd * abfd)
 /* The final processing done just before writing out an ARC ELF object file.
    This gets the ARC architecture right based on the machine number.  */
 
-static void
-arc_elf_final_write_processing (bfd * abfd,
-                               bfd_boolean linker ATTRIBUTE_UNUSED)
+static bfd_boolean
+arc_elf_final_write_processing (bfd *abfd)
 {
   unsigned long emf;
   int osver = bfd_elf_get_obj_attr_int (abfd, OBJ_ATTR_PROC,
@@ -1037,20 +1051,12 @@ arc_elf_final_write_processing (bfd * abfd,
 
   switch (bfd_get_mach (abfd))
     {
-    case bfd_mach_arc_arc600:
-      emf = EM_ARC_COMPACT;
-      break;
-    case bfd_mach_arc_arc601:
-      emf = EM_ARC_COMPACT;
-      break;
-    case bfd_mach_arc_arc700:
-      emf = EM_ARC_COMPACT;
-      break;
     case bfd_mach_arc_arcv2:
       emf = EM_ARC_COMPACT2;
       break;
     default:
-      return;
+      emf = EM_ARC_COMPACT;
+      break;
     }
 
   elf_elfheader (abfd)->e_machine = emf;
@@ -1061,7 +1067,8 @@ arc_elf_final_write_processing (bfd * abfd,
   else
     e_flags |= E_ARC_OSABI_V3;
 
-  elf_elfheader (abfd)->e_flags |=  e_flags;
+  elf_elfheader (abfd)->e_flags |= e_flags;
+  return _bfd_elf_final_write_processing (abfd);
 }
 
 #ifdef ARC_ENABLE_DEBUG
@@ -1089,7 +1096,8 @@ debug_arc_reloc (struct arc_relocation_data reloc_data)
        ARC_DEBUG (", output_section->vma = 0x%08x",
                   ((unsigned int) reloc_data.sym_section->output_section->vma));
       ARC_DEBUG ("\n");
-      if (reloc_data.sym_section->owner && reloc_data.sym_section->owner->filename)
+      if (reloc_data.sym_section->owner
+         && reloc_data.sym_section->owner->filename)
        ARC_DEBUG ("  file: %s\n", reloc_data.sym_section->owner->filename);
     }
   else
@@ -1243,11 +1251,11 @@ arc_special_overflow_checks (const struct arc_relocation_data reloc_data,
       else                                                             \
        ARC_DEBUG ("symbol_section->vma = NULL\n");                     \
       if (input_section->output_section != NULL)                       \
-       ARC_DEBUG ("symbol_section->vma = %#lx\n",                      \
+       ARC_DEBUG ("input_section->vma = %#lx\n",                       \
                   input_section->output_section->vma                   \
                   + input_section->output_offset);                     \
       else                                                             \
-       ARC_DEBUG ("symbol_section->vma = NULL\n");                     \
+       ARC_DEBUG ("input_section->vma = NULL\n");                      \
       ARC_DEBUG ("PCL = %#lx\n", P);                                   \
       ARC_DEBUG ("P = %#lx\n", P);                                     \
       ARC_DEBUG ("G = %#lx\n", G);                                     \
@@ -1305,25 +1313,25 @@ arc_do_relocation (bfd_byte * contents,
 
   switch (reloc_data.howto->size)
     {
-      case 2:
-       insn = arc_bfd_get_32 (abfd,
-                              contents + reloc_data.reloc_offset,
-                              reloc_data.input_section);
-       break;
-      case 1:
-       insn = arc_bfd_get_16 (abfd,
-                              contents + reloc_data.reloc_offset,
-                              reloc_data.input_section);
-       break;
-      case 0:
-       insn = arc_bfd_get_8 (abfd,
-                              contents + reloc_data.reloc_offset,
-                              reloc_data.input_section);
-       break;
-      default:
-       insn = 0;
-       BFD_ASSERT (0);
-       break;
+    case 2:
+      insn = arc_bfd_get_32 (abfd,
+                            contents + reloc_data.reloc_offset,
+                            reloc_data.input_section);
+      break;
+    case 1:
+      insn = arc_bfd_get_16 (abfd,
+                            contents + reloc_data.reloc_offset,
+                            reloc_data.input_section);
+      break;
+    case 0:
+      insn = arc_bfd_get_8 (abfd,
+                           contents + reloc_data.reloc_offset,
+                           reloc_data.input_section);
+      break;
+    default:
+      insn = 0;
+      BFD_ASSERT (0);
+      break;
     }
 
   orig_insn = insn;
@@ -1332,9 +1340,9 @@ arc_do_relocation (bfd_byte * contents,
     {
 #include "elf/arc-reloc.def"
 
-      default:
-       BFD_ASSERT (0);
-       break;
+    default:
+      BFD_ASSERT (0);
+      break;
     }
 
   /* Check for relocation overflow.  */
@@ -1361,25 +1369,25 @@ arc_do_relocation (bfd_byte * contents,
   /* Write updated instruction back to memory.  */
   switch (reloc_data.howto->size)
     {
-      case 2:
-       arc_bfd_put_32 (abfd, insn,
-                      contents + reloc_data.reloc_offset,
-                      reloc_data.input_section);
-       break;
-      case 1:
+    case 2:
+      arc_bfd_put_32 (abfd, insn,
+                     contents + reloc_data.reloc_offset,
+                     reloc_data.input_section);
+      break;
+    case 1:
        arc_bfd_put_16 (abfd, insn,
-                      contents + reloc_data.reloc_offset,
-                      reloc_data.input_section);
-       break;
-      case 0:
-       arc_bfd_put_8 (abfd, insn,
-                      contents + reloc_data.reloc_offset,
-                      reloc_data.input_section);
-       break;
-      default:
-       ARC_DEBUG ("size = %d\n", reloc_data.howto->size);
-       BFD_ASSERT (0);
+                       contents + reloc_data.reloc_offset,
+                       reloc_data.input_section);
        break;
+    case 0:
+      arc_bfd_put_8 (abfd, insn,
+                    contents + reloc_data.reloc_offset,
+                    reloc_data.input_section);
+      break;
+    default:
+      ARC_DEBUG ("size = %d\n", reloc_data.howto->size);
+      BFD_ASSERT (0);
+      break;
     }
 
   return bfd_reloc_ok;
@@ -1774,6 +1782,7 @@ elf_arc_relocate_section (bfd *                     output_bfd,
          case R_ARC_PC32:
          case R_ARC_32_PCREL:
            if (bfd_link_pic (info)
+               && (input_section->flags & SEC_ALLOC) != 0
                && (!IS_ARC_PCREL_TYPE (r_type)
                    || (h != NULL
                        && h->dynindx != -1
@@ -2986,6 +2995,152 @@ elf32_arc_section_from_shdr (bfd *abfd,
   return TRUE;
 }
 
+/* Relaxation hook.
+
+   These are the current relaxing opportunities available:
+
+   * R_ARC_GOTPC32 => R_ARC_PCREL.
+
+*/
+
+static bfd_boolean
+arc_elf_relax_section (bfd *abfd, asection *sec,
+                      struct bfd_link_info *link_info, bfd_boolean *again)
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  Elf_Internal_Rela *internal_relocs;
+  Elf_Internal_Rela *irel, *irelend;
+  bfd_byte *contents = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
+
+  /* Assume nothing changes.  */
+  *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 (bfd_link_relocatable (link_info)
+      || (sec->flags & SEC_RELOC) == 0
+      || sec->reloc_count == 0
+      || (sec->flags & SEC_CODE) == 0)
+    return TRUE;
+
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+
+  /* Get a copy of the native relocations.  */
+  internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
+                                               link_info->keep_memory);
+  if (internal_relocs == NULL)
+    goto error_return;
+
+  /* Walk through them looking for relaxing opportunities.  */
+  irelend = internal_relocs + sec->reloc_count;
+  for (irel = internal_relocs; irel < irelend; irel++)
+    {
+      /* If this isn't something that can be relaxed, then ignore
+         this reloc.  */
+      if (ELF32_R_TYPE (irel->r_info) != (int) R_ARC_GOTPC32)
+        continue;
+
+      /* Get the section contents if we haven't done so already.  */
+      if (contents == NULL)
+        {
+          /* Get cached copy if it exists.  */
+          if (elf_section_data (sec)->this_hdr.contents != NULL)
+            contents = elf_section_data (sec)->this_hdr.contents;
+          /* Go get them off disk.  */
+          else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
+            goto error_return;
+        }
+
+      /* Read this BFD's local symbols if we haven't done so already.  */
+      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
+        {
+          isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+          if (isymbuf == NULL)
+            isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+                                            symtab_hdr->sh_info, 0,
+                                            NULL, NULL, NULL);
+          if (isymbuf == NULL)
+            goto error_return;
+        }
+
+      struct elf_link_hash_entry *htop = NULL;
+
+      if (ELF32_R_SYM (irel->r_info) >= symtab_hdr->sh_info)
+       {
+         /* An external symbol.  */
+         unsigned int indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
+         htop = elf_sym_hashes (abfd)[indx];
+       }
+
+      if (ELF32_R_TYPE (irel->r_info) == (int) R_ARC_GOTPC32
+         && SYMBOL_REFERENCES_LOCAL (link_info, htop))
+       {
+         unsigned int code;
+
+         /* Get the opcode.  */
+         code = bfd_get_32_me (abfd, contents + irel->r_offset - 4);
+
+         /* Note that we've changed the relocs, section contents, etc.  */
+         elf_section_data (sec)->relocs = internal_relocs;
+         elf_section_data (sec)->this_hdr.contents = contents;
+         symtab_hdr->contents = (unsigned char *) isymbuf;
+
+         /* Fix the relocation's type.  */
+         irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_ARC_PC32);
+
+         /* ld rA,[pcl,symbol@tgot] -> add rA,pcl,symbol@pcl.  */
+         /* 0010 0bbb aa11 0ZZX DBBB 1111 10AA AAAA.
+                  111 00    000 0111        xx xxxx*/
+         code &= ~0x27307F80;
+         BFD_ASSERT (code <= 62UL);
+         code |= 0x27007F80;
+
+         /* Write back the new instruction.  */
+         bfd_put_32_me (abfd, code, contents + irel->r_offset - 4);
+
+         /* The size isn't changed, don't redo.  */
+         *again = FALSE;
+       }
+    }
+
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
+    {
+      if (!link_info->keep_memory)
+        free (isymbuf);
+      else
+       /* Cache the symbols for elf_link_input_bfd.  */
+       symtab_hdr->contents = (unsigned char *) isymbuf;
+    }
+
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
+    {
+      if (!link_info->keep_memory)
+        free (contents);
+      else
+       /* Cache the section contents for elf_link_input_bfd.  */
+       elf_section_data (sec)->this_hdr.contents = contents;
+    }
+
+  if (elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
+
+  return TRUE;
+
+ error_return:
+  if (symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
+  if (elf_section_data (sec)->this_hdr.contents != contents)
+    free (contents);
+  if (elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
+
+  return FALSE;
+}
+
 #define TARGET_LITTLE_SYM   arc_elf32_le_vec
 #define TARGET_LITTLE_NAME  "elf32-littlearc"
 #define TARGET_BIG_SYM     arc_elf32_be_vec
@@ -3003,6 +3158,7 @@ elf32_arc_section_from_shdr (bfd *abfd,
 #define bfd_elf32_bfd_set_private_flags                arc_elf_set_private_flags
 #define bfd_elf32_bfd_print_private_bfd_data    arc_elf_print_private_bfd_data
 #define bfd_elf32_bfd_copy_private_bfd_data     arc_elf_copy_private_bfd_data
+#define bfd_elf32_bfd_relax_section            arc_elf_relax_section
 
 #define elf_info_to_howto_rel               arc_info_to_howto_rel
 #define elf_backend_object_p                arc_elf_object_p
This page took 0.028774 seconds and 4 git commands to generate.