Add new target_read_raw_memory function, and consolidate comments.
[deliverable/binutils-gdb.git] / bfd / elf32-arm.c
index fe01c9a5aca6a635248ace15e918d18e13335463..70d6ac09357cebcd6b6f25c993344c906d08dc58 100644 (file)
@@ -2415,6 +2415,33 @@ static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_tls_pic[] =
   DATA_WORD (0, R_ARM_REL32, -4),    /* dcd  R_ARM_REL32(X) */
 };
 
+/* NaCl ARM -> ARM long branch stub.  */
+static const insn_sequence elf32_arm_stub_long_branch_arm_nacl[] =
+{
+  ARM_INSN (0xe59fc00c),               /* ldr  ip, [pc, #12] */
+  ARM_INSN (0xe3ccc13f),               /* bic  ip, ip, #0xc000000f */
+  ARM_INSN (0xe12fff1c),                /* bx  ip */
+  ARM_INSN (0xe320f000),                /* nop */
+  ARM_INSN (0xe125be70),                /* bkpt        0x5be0 */
+  DATA_WORD (0, R_ARM_ABS32, 0),        /* dcd R_ARM_ABS32(X) */
+  DATA_WORD (0, R_ARM_NONE, 0),         /* .word 0 */
+  DATA_WORD (0, R_ARM_NONE, 0),         /* .word 0 */
+};
+
+/* NaCl ARM -> ARM long branch stub, PIC.  */
+static const insn_sequence elf32_arm_stub_long_branch_arm_nacl_pic[] =
+{
+  ARM_INSN (0xe59fc00c),               /* ldr  ip, [pc, #12] */
+  ARM_INSN (0xe08cc00f),                /* add ip, ip, pc */
+  ARM_INSN (0xe3ccc13f),               /* bic  ip, ip, #0xc000000f */
+  ARM_INSN (0xe12fff1c),                /* bx  ip */
+  ARM_INSN (0xe125be70),                /* bkpt        0x5be0 */
+  DATA_WORD (0, R_ARM_REL32, 8),        /* dcd R_ARM_REL32(X+8) */
+  DATA_WORD (0, R_ARM_NONE, 0),         /* .word 0 */
+  DATA_WORD (0, R_ARM_NONE, 0),         /* .word 0 */
+};
+
+
 /* Cortex-A8 erratum-workaround stubs.  */
 
 /* Stub used for conditional branches (which may be beyond +/-1MB away, so we
@@ -2491,6 +2518,8 @@ static const insn_sequence elf32_arm_stub_a8_veneer_blx[] =
   DEF_STUB(long_branch_thumb_only_pic) \
   DEF_STUB(long_branch_any_tls_pic) \
   DEF_STUB(long_branch_v4t_thumb_tls_pic) \
+  DEF_STUB(long_branch_arm_nacl) \
+  DEF_STUB(long_branch_arm_nacl_pic) \
   DEF_STUB(a8_veneer_b_cond) \
   DEF_STUB(a8_veneer_b) \
   DEF_STUB(a8_veneer_bl) \
@@ -2983,7 +3012,7 @@ struct elf32_arm_link_hash_table
   bfd *stub_bfd;
 
   /* Linker call-backs.  */
-  asection * (*add_stub_section) (const char *, asection *);
+  asection * (*add_stub_section) (const char *, asection *, unsigned int);
   void (*layout_sections_again) (void);
 
   /* Array to keep track of which stub sections have been created, and
@@ -3580,6 +3609,12 @@ arm_type_of_stub (struct bfd_link_info *info,
 
   r_type = ELF32_R_TYPE (rel->r_info);
 
+  /* ST_BRANCH_TO_ARM is nonsense to thumb-only targets when we
+     are considering a function call relocation.  */
+  if (thumb_only && (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24)
+      && branch_type == ST_BRANCH_TO_ARM)
+    branch_type = ST_BRANCH_TO_THUMB;
+
   /* For TLS call relocs, it is the caller's responsibility to provide
      the address of the appropriate trampoline.  */
   if (r_type != R_ARM_TLS_CALL
@@ -3772,9 +3807,13 @@ arm_type_of_stub (struct bfd_link_info *info,
                ? (r_type == R_ARM_TLS_CALL
                   /* TLS PIC Stub */
                   ? arm_stub_long_branch_any_tls_pic
-                  : arm_stub_long_branch_any_arm_pic)
+                  : (globals->nacl_p
+                     ? arm_stub_long_branch_arm_nacl_pic
+                     : arm_stub_long_branch_any_arm_pic))
                /* non-PIC stubs.  */
-               : arm_stub_long_branch_any_any;
+               : (globals->nacl_p
+                  ? arm_stub_long_branch_arm_nacl
+                  : arm_stub_long_branch_any_any);
            }
        }
     }
@@ -3910,7 +3949,8 @@ elf32_arm_create_or_find_stub_sec (asection **link_sec_p, asection *section,
 
          memcpy (s_name, link_sec->name, namelen);
          memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX));
-         stub_sec = (*htab->add_stub_section) (s_name, link_sec);
+         stub_sec = (*htab->add_stub_section) (s_name, link_sec,
+                                               htab->nacl_p ? 4 : 3);
          if (stub_sec == NULL)
            return NULL;
          htab->stub_group[link_sec->id].stub_sec = stub_sec;
@@ -4043,6 +4083,10 @@ arm_stub_required_alignment (enum elf32_arm_stub_type stub_type)
     case arm_stub_a8_veneer_blx:
       return 4;
 
+    case arm_stub_long_branch_arm_nacl:
+    case arm_stub_long_branch_arm_nacl_pic:
+      return 16;
+
     default:
       abort ();  /* Should be unreachable.  */
     }
@@ -4052,7 +4096,7 @@ static bfd_boolean
 arm_build_one_stub (struct bfd_hash_entry *gen_entry,
                    void * in_arg)
 {
-#define MAXRELOCS 2
+#define MAXRELOCS 3
   struct elf32_arm_stub_hash_entry *stub_entry;
   struct elf32_arm_link_hash_table *globals;
   struct bfd_link_info *info;
@@ -4864,7 +4908,8 @@ elf32_arm_size_stubs (bfd *output_bfd,
                      bfd *stub_bfd,
                      struct bfd_link_info *info,
                      bfd_signed_vma group_size,
-                     asection * (*add_stub_section) (const char *, asection *),
+                     asection * (*add_stub_section) (const char *, asection *,
+                                                     unsigned int),
                      void (*layout_sections_again) (void))
 {
   bfd_size_type stub_group_size;
@@ -7448,9 +7493,11 @@ arm_movt_immediate (bfd_vma value)
 
    ROOT_PLT points to the offset of the PLT entry from the start of its
    section (.iplt or .plt).  ARM_PLT points to the symbol's ARM-specific
-   bookkeeping information.  */
+   bookkeeping information.
 
-static void
+   Returns FALSE if there was a problem.  */
+
+static bfd_boolean
 elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info,
                              union gotplt_union *root_plt,
                              struct arm_plt_info *arm_plt,
@@ -7640,6 +7687,16 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info,
                        | (tail_displacement & 0x00ffffff),
                        ptr + 12);
        }
+      else if (using_thumb_only (htab))
+       {
+         /* PR ld/16017: Do not generate ARM instructions for
+            the PLT if compiling for a thumb-only target.
+
+            FIXME: We ought to be able to generate thumb PLT instructions...  */
+         _bfd_error_handler (_("%B: Warning: thumb mode PLT generation not currently supported"),
+                             output_bfd);
+         return FALSE;
+       }
       else
        {
          /* Calculate the displacement between the PLT slot and the
@@ -7705,6 +7762,8 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info,
       loc = srel->contents + plt_index * RELOC_SIZE (htab);
       SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
     }
+
+  return TRUE;
 }
 
 /* Some relocations map to different relocations depending on the
@@ -8084,6 +8143,14 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
   else
     addend = signed_addend = rel->r_addend;
 
+  /* ST_BRANCH_TO_ARM is nonsense to thumb-only targets when we
+     are resolving a function call relocation.  */
+  if (using_thumb_only (globals)
+      && (r_type == R_ARM_THM_CALL
+         || r_type == R_ARM_THM_JUMP24)
+      && branch_type == ST_BRANCH_TO_ARM)
+    branch_type = ST_BRANCH_TO_THUMB;
+
   /* Record the symbol information that should be used in dynamic
      relocations.  */
   dynreloc_st_type = st_type;
@@ -8112,9 +8179,11 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
            plt_offset--;
          else
            {
-             elf32_arm_populate_plt_entry (output_bfd, info, root_plt, arm_plt,
-                                           -1, dynreloc_value);
-             root_plt->offset |= 1;
+             if (elf32_arm_populate_plt_entry (output_bfd, info, root_plt, arm_plt,
+                                               -1, dynreloc_value))
+               root_plt->offset |= 1;
+             else
+               return bfd_reloc_notsupported;
            }
 
          /* Static relocations always resolve to the .iplt entry.  */
@@ -9799,10 +9868,8 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
        bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
        bfd_vma pc = input_section->output_section->vma
                     + input_section->output_offset + rel->r_offset;
-       /* sb should be the origin of the *segment* containing the symbol.
-          It is not clear how to obtain this OS-dependent value, so we
-          make an arbitrary choice of zero.  */
-       bfd_vma sb = 0;
+       /* sb is the origin of the *segment* containing the symbol.  */
+       bfd_vma sb = sym_sec ? sym_sec->output_section->vma : 0;
        bfd_vma residual;
        bfd_vma g_n;
        bfd_signed_vma signed_value;
@@ -9935,7 +10002,8 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
        bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
        bfd_vma pc = input_section->output_section->vma
                     + input_section->output_offset + rel->r_offset;
-       bfd_vma sb = 0; /* See note above.  */
+       /* sb is the origin of the *segment* containing the symbol.  */
+       bfd_vma sb = sym_sec ? sym_sec->output_section->vma : 0;
        bfd_vma residual;
        bfd_signed_vma signed_value;
        int group = 0;
@@ -10018,7 +10086,8 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
        bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
        bfd_vma pc = input_section->output_section->vma
                     + input_section->output_offset + rel->r_offset;
-       bfd_vma sb = 0; /* See note above.  */
+       /* sb is the origin of the *segment* containing the symbol.  */
+       bfd_vma sb = sym_sec ? sym_sec->output_section->vma : 0;
        bfd_vma residual;
        bfd_signed_vma signed_value;
        int group = 0;
@@ -10101,7 +10170,8 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
        bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
        bfd_vma pc = input_section->output_section->vma
                     + input_section->output_offset + rel->r_offset;
-       bfd_vma sb = 0; /* See note above.  */
+       /* sb is the origin of the *segment* containing the symbol.  */
+       bfd_vma sb = sym_sec ? sym_sec->output_section->vma : 0;
        bfd_vma residual;
        bfd_signed_vma signed_value;
        int group = 0;
@@ -10456,12 +10526,12 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
        }
       else
        {
-         bfd_boolean warned;
+         bfd_boolean warned, ignored;
 
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
                                   r_symndx, symtab_hdr, sym_hashes,
                                   h, sec, relocation,
-                                  unresolved_reloc, warned);
+                                  unresolved_reloc, warned, ignored);
 
          sym_type = h->type;
        }
@@ -13340,12 +13410,6 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
       h->root.u.def.value = th->root.u.def.value & ~1;
     }
 
-  /* Make sure we are not applying ST_BRANCH_TO_ARM to symbols
-     for thumb-only targets.  */
-  if (using_thumb_only (htab)
-      && h->target_internal == ST_BRANCH_TO_ARM)
-    h->target_internal = ST_BRANCH_TO_THUMB;
-
   if (eh->dyn_relocs == NULL)
     return TRUE;
 
@@ -13969,8 +14033,9 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd,
       if (!eh->is_iplt)
        {
          BFD_ASSERT (h->dynindx != -1);
-         elf32_arm_populate_plt_entry (output_bfd, info, &h->plt, &eh->plt,
-                                       h->dynindx, 0);
+         if (! elf32_arm_populate_plt_entry (output_bfd, info, &h->plt, &eh->plt,
+                                             h->dynindx, 0))
+           return FALSE;
        }
 
       if (!h->def_regular)
@@ -15812,6 +15877,14 @@ elf32_arm_nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
          && nacl_modify_segment_map (abfd, info));
 }
 
+static void
+elf32_arm_nacl_final_write_processing (bfd *abfd, bfd_boolean linker)
+{
+  elf32_arm_final_write_processing (abfd, linker);
+  nacl_final_write_processing (abfd, linker);
+}
+
+
 #undef elf32_bed
 #define elf32_bed                      elf32_arm_nacl_bed
 #undef  bfd_elf32_bfd_link_hash_table_create
@@ -15823,9 +15896,14 @@ elf32_arm_nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
 #define        elf_backend_modify_segment_map          elf32_arm_nacl_modify_segment_map
 #undef elf_backend_modify_program_headers
 #define        elf_backend_modify_program_headers      nacl_modify_program_headers
+#undef  elf_backend_final_write_processing
+#define elf_backend_final_write_processing     elf32_arm_nacl_final_write_processing
 
 #undef ELF_MAXPAGESIZE
 #define ELF_MAXPAGESIZE                        0x10000
+#undef ELF_MINPAGESIZE
+#undef ELF_COMMONPAGESIZE
+
 
 #include "elf32-target.h"
 
@@ -15834,6 +15912,13 @@ elf32_arm_nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
 #undef elf_backend_modify_segment_map
 #define elf_backend_modify_segment_map         elf32_arm_modify_segment_map
 #undef elf_backend_modify_program_headers
+#undef  elf_backend_final_write_processing
+#define elf_backend_final_write_processing     elf32_arm_final_write_processing
+#undef ELF_MINPAGESIZE
+#define ELF_MINPAGESIZE                        0x1000
+#undef ELF_COMMONPAGESIZE
+#define ELF_COMMONPAGESIZE             0x1000
+
 
 /* VxWorks Targets.  */
 
This page took 0.031546 seconds and 4 git commands to generate.