Create sdynrelro for elfn32 mips too
[deliverable/binutils-gdb.git] / bfd / elfnn-aarch64.c
index 4ebdbe20d7178ce46e6b8f2a77784ec00c2fff92..0103b01ee91114bae798b76e82c7dd3d375c31bd 100644 (file)
@@ -2296,10 +2296,6 @@ struct elf_aarch64_link_hash_table
   /* The number of bytes in the subsequent PLT etries.  */
   bfd_size_type plt_entry_size;
 
-  /* Short-cuts to get to dynamic linker sections.  */
-  asection *sdynbss;
-  asection *srelbss;
-
   /* Small local sym cache.  */
   struct sym_cache sym_cache;
 
@@ -5841,24 +5837,29 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
       else
        {
          /* GD->IE relaxation
-            ADD  x0, #:tlsgd_lo12:var  => ldr  x0, [x0, #:gottprel_lo12:var]
+            ADD  x0, #:tlsgd_lo12:var  => ldr  R0, [x0, #:gottprel_lo12:var]
             BL   __tls_get_addr        => mrs  x1, tpidr_el0
               R_AARCH64_CALL26
-            NOP                        => add  x0, x1, x0
-          */
+            NOP                        => add  R0, R1, R0
+
+            Where R is x for lp64 mode, and w for ilp32 mode.  */
 
          BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (CALL26));
 
          /* Remove the relocation on the BL instruction.  */
          rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
 
-         bfd_putl32 (0xf9400000, contents + rel->r_offset);
-
          /* We choose to fixup the BL and NOP instructions using the
             offset from the second relocation to allow flexibility in
             scheduling instructions between the ADD and BL.  */
-         bfd_putl32 (0xd53bd041, contents + rel[1].r_offset);
+#if ARCH_SIZE == 32
+         bfd_putl32 (0xb9400000, contents + rel->r_offset);
+         bfd_putl32 (0x0b000020, contents + rel[1].r_offset + 4);
+#else
+         bfd_putl32 (0xf9400000, contents + rel->r_offset);
          bfd_putl32 (0x8b000020, contents + rel[1].r_offset + 4);
+#endif
+         bfd_putl32 (0xd53bd041, contents + rel[1].r_offset);
          return bfd_reloc_continue;
        }
 
@@ -5946,8 +5947,9 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
     case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
       /* LD->LE relaxation (tiny):
         adr  x0, :tlsldm:x  => mrs x0, tpidr_el0
-        bl   __tls_get_addr => add x0, x0, TCB_SIZE
-       */
+        bl   __tls_get_addr => add R0, R0, TCB_SIZE
+
+        Where R is x for lp64 mode, and w for ilp32 mode.  */
       if (is_local)
        {
          BFD_ASSERT (rel->r_offset + 4 == rel[1].r_offset);
@@ -5955,7 +5957,11 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
          /* No need of CALL26 relocation for tls_get_addr.  */
          rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
          bfd_putl32 (0xd53bd040, contents + rel->r_offset + 0);
+#if ARCH_SIZE == 64
          bfd_putl32 (0x91004000, contents + rel->r_offset + 4);
+#else
+         bfd_putl32 (0x11002000, contents + rel->r_offset + 4);
+#endif
          return bfd_reloc_ok;
        }
       return bfd_reloc_continue;
@@ -5973,17 +5979,22 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
 
     case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC:
       /* LD->LE relaxation (small):
-        add   x0, #:tlsldm_lo12:x => add x0, x0, TCB_SIZE
+        add   x0, #:tlsldm_lo12:x => add R0, R0, TCB_SIZE
         bl   __tls_get_addr       => nop
-       */
+
+        Where R is x for lp64 mode, and w for ilp32 mode.  */
       if (is_local)
        {
          BFD_ASSERT (rel->r_offset + 4 == rel[1].r_offset);
          BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (CALL26));
          /* No need of CALL26 relocation for tls_get_addr.  */
          rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+#if ARCH_SIZE == 64
          bfd_putl32 (0x91004000, contents + rel->r_offset + 0);
-         bfd_putl32 (0xd503201f, contents + rel->r_offset + 4);
+#else
+         bfd_putl32 (0x11002000, contents + rel->r_offset + 0);
+#endif
+         bfd_putl32 (INSN_NOP, contents + rel->r_offset + 4);
          return bfd_reloc_ok;
        }
       return bfd_reloc_continue;
@@ -6822,7 +6833,7 @@ elfNN_aarch64_adjust_dynamic_symbol (struct bfd_link_info *info,
                                     struct elf_link_hash_entry *h)
 {
   struct elf_aarch64_link_hash_table *htab;
-  asection *s;
+  asection *s, *srel;
 
   /* If this is a function, put it in the procedure linkage table.  We
      will fill in the contents of the procedure linkage table later,
@@ -6899,14 +6910,22 @@ elfNN_aarch64_adjust_dynamic_symbol (struct bfd_link_info *info,
   /* We must generate a R_AARCH64_COPY reloc to tell the dynamic linker
      to copy the initial value out of the dynamic object and into the
      runtime process image.  */
+  if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+    {
+      s = htab->root.sdynrelro;
+      srel = htab->root.sreldynrelro;
+    }
+  else
+    {
+      s = htab->root.sdynbss;
+      srel = htab->root.srelbss;
+    }
   if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
     {
-      htab->srelbss->size += RELOC_SIZE (htab);
+      srel->size += RELOC_SIZE (htab);
       h->needs_copy = 1;
     }
 
-  s = htab->sdynbss;
-
   return _bfd_elf_adjust_dynamic_copy (info, h, s);
 
 }
@@ -6939,8 +6958,7 @@ aarch64_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
   struct elf_link_hash_table *htab = elf_hash_table (info);
 
   /* This function may be called more than once.  */
-  s = bfd_get_linker_section (abfd, ".got");
-  if (s != NULL)
+  if (htab->sgot != NULL)
     return TRUE;
 
   flags = bed->dynamic_sec_flags;
@@ -7900,24 +7918,11 @@ static bfd_boolean
 elfNN_aarch64_create_dynamic_sections (bfd *dynobj,
                                       struct bfd_link_info *info)
 {
-  struct elf_aarch64_link_hash_table *htab;
-
   /* We need to create .got section.  */
   if (!aarch64_elf_create_got_section (dynobj, info))
     return FALSE;
 
-  if (!_bfd_elf_create_dynamic_sections (dynobj, info))
-    return FALSE;
-
-  htab = elf_aarch64_hash_table (info);
-  htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
-  if (!bfd_link_pic (info))
-    htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
-
-  if (!htab->sdynbss || (!bfd_link_pic (info) && !htab->srelbss))
-    abort ();
-
-  return TRUE;
+  return _bfd_elf_create_dynamic_sections (dynobj, info);
 }
 
 
@@ -8519,7 +8524,9 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
          || s == htab->root.sgot
          || s == htab->root.sgotplt
          || s == htab->root.iplt
-         || s == htab->root.igotplt || s == htab->sdynbss)
+         || s == htab->root.igotplt
+         || s == htab->root.sdynbss
+         || s == htab->root.sdynrelro)
        {
          /* Strip this section if we don't need it; see the
             comment below.  */
@@ -8923,6 +8930,7 @@ do_glob_dat:
   if (h->needs_copy)
     {
       Elf_Internal_Rela rela;
+      asection *s;
       bfd_byte *loc;
 
       /* This symbol needs a copy reloc.  Set it up.  */
@@ -8930,7 +8938,7 @@ do_glob_dat:
       if (h->dynindx == -1
          || (h->root.type != bfd_link_hash_defined
              && h->root.type != bfd_link_hash_defweak)
-         || htab->srelbss == NULL)
+         || htab->root.srelbss == NULL)
        abort ();
 
       rela.r_offset = (h->root.u.def.value
@@ -8938,8 +8946,11 @@ do_glob_dat:
                       + h->root.u.def.section->output_offset);
       rela.r_info = ELFNN_R_INFO (h->dynindx, AARCH64_R (COPY));
       rela.r_addend = 0;
-      loc = htab->srelbss->contents;
-      loc += htab->srelbss->reloc_count++ * RELOC_SIZE (htab);
+      if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+       s = htab->root.sreldynrelro;
+      else
+       s = htab->root.srelbss;
+      loc = s->contents + s->reloc_count++ * RELOC_SIZE (htab);
       bfd_elfNN_swap_reloca_out (output_bfd, &rela, loc);
     }
 
@@ -9067,21 +9078,6 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd,
              dyn.d_un.d_val = s->size;
              break;
 
-           case DT_RELASZ:
-             /* The procedure linkage table relocs (DT_JMPREL) should
-                not be included in the overall relocs (DT_RELA).
-                Therefore, we override the DT_RELASZ entry here to
-                make it not include the JMPREL relocs.  Since the
-                linker script arranges for .rela.plt to follow all
-                other relocation sections, we don't have to worry
-                about changing the DT_RELA entry.  */
-             if (htab->root.srelplt != NULL)
-               {
-                 s = htab->root.srelplt;
-                 dyn.d_un.d_val -= s->size;
-               }
-             break;
-
            case DT_TLSDESC_PLT:
              s = htab->root.splt;
              dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
@@ -9407,10 +9403,12 @@ const struct elf_size_info elfNN_aarch64_size_info =
 #define elf_backend_plt_readonly       1
 #define elf_backend_want_got_plt       1
 #define elf_backend_want_plt_sym       0
+#define elf_backend_want_dynrelro      1
 #define elf_backend_may_use_rel_p      0
 #define elf_backend_may_use_rela_p     1
 #define elf_backend_default_use_rela_p 1
 #define elf_backend_rela_normal        1
+#define elf_backend_dtrel_excludes_plt 1
 #define elf_backend_got_header_size (GOT_ENTRY_SIZE * 3)
 #define elf_backend_default_execstack  0
 #define elf_backend_extern_protected_data 1
This page took 0.026476 seconds and 4 git commands to generate.