Files removed as of the 1999-08-23 snapshot.
[deliverable/binutils-gdb.git] / bfd / elf32-arm.h
index 066cbc3e78309ac7e94193875b8831fb96013d17..fe7fa82cb88bd755d293557ac95cf8d4b63c4b6c 100644 (file)
@@ -50,6 +50,12 @@ static void record_thumb_to_arm_glue
   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
 static void elf32_arm_post_process_headers
   PARAMS ((bfd *, struct bfd_link_info *));
+static int elf32_arm_to_thumb_stub
+  PARAMS ((struct bfd_link_info *, const char *, bfd *, bfd *, asection *,
+          bfd_byte *, asection *, bfd_vma, bfd_signed_vma, bfd_vma));
+static int elf32_thumb_to_arm_stub
+  PARAMS ((struct bfd_link_info *, const char *, bfd *, bfd *, asection *,
+          bfd_byte *, asection *, bfd_vma, bfd_signed_vma, bfd_vma));
 
 /* The linker script knows the section names for placement.
    The entry_names are used to do simple name mangling on the stubs.
@@ -625,7 +631,6 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)
        {
          long r_type;
          unsigned long r_index;
-         unsigned char code;
 
          struct elf_link_hash_entry *h;
 
@@ -710,7 +715,7 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)
            case R_ARM_THM_PC22:
              /* This one is a call from thumb code.  We look
                 up the target of the call. If it is not a thumb
-                 target, we insert glue. */
+                 target, we insert glue.  */
 
              if (ELF_ST_TYPE (h->type) != STT_ARM_TFUNC)
                record_thumb_to_arm_glue (link_info, h);
@@ -796,23 +801,23 @@ insert_thumb_branch (br_insn, rel_off)
 static int
 elf32_thumb_to_arm_stub (info, name, input_bfd, output_bfd, input_section,
                         hit_data, sym_sec, offset, addend, val)
-     struct bfd_link_info *info;
-     char *name;
-     bfd *input_bfd;
-     bfd *output_bfd;
-     asection *input_section;
-     bfd_byte *hit_data;
-     asection *sym_sec;
-     int offset;
-     int addend;
-     bfd_vma val;
+     struct bfd_link_info * info;
+     const char *           name;
+     bfd *                  input_bfd;
+     bfd *                  output_bfd;
+     asection *             input_section;
+     bfd_byte *             hit_data;
+     asection *             sym_sec;
+     bfd_vma                offset;
+     bfd_signed_vma         addend;
+     bfd_vma                val;
 {
-  asection *s = 0;
+  asection * s = 0;
   long int my_offset;
   unsigned long int tmp;
   long int ret_offset;
-  struct elf_link_hash_entry *myh;
-  struct elf32_arm_link_hash_table *globals;
+  struct elf_link_hash_entry * myh;
+  struct elf32_arm_link_hash_table * globals;
 
   myh = find_thumb_glue (info, name, input_bfd);
   if (myh == NULL)
@@ -896,24 +901,23 @@ elf32_thumb_to_arm_stub (info, name, input_bfd, output_bfd, input_section,
 static int
 elf32_arm_to_thumb_stub (info, name, input_bfd, output_bfd, input_section,
                         hit_data, sym_sec, offset, addend, val)
-
-     struct bfd_link_info *info;
-     char *name;
-     bfd *input_bfd;
-     bfd *output_bfd;
-     asection *input_section;
-     bfd_byte *hit_data;
-     asection *sym_sec;
-     int offset;
-     int addend;
-     bfd_vma val;
+     struct bfd_link_info * info;
+     const char *           name;
+     bfd *                  input_bfd;
+     bfd *                  output_bfd;
+     asection *             input_section;
+     bfd_byte *             hit_data;
+     asection *             sym_sec;
+     bfd_vma                offset;
+     bfd_signed_vma         addend;
+     bfd_vma                val;
 {
   unsigned long int tmp;
   long int my_offset;
-  asection *s;
+  asection * s;
   long int ret_offset;
-  struct elf_link_hash_entry *myh;
-  struct elf32_arm_link_hash_table *globals;
+  struct elf_link_hash_entry * myh;
+  struct elf32_arm_link_hash_table * globals;
 
   myh = find_arm_glue (info, name, input_bfd);
   if (myh == NULL)
@@ -971,13 +975,12 @@ elf32_arm_to_thumb_stub (info, name, input_bfd, output_bfd, input_section,
        + input_section->output_section->vma
        + offset + addend)
     - 8;
-
+  
   tmp = tmp | ((ret_offset >> 2) & 0x00FFFFFF);
 
   bfd_put_32 (output_bfd, tmp, hit_data
              - input_section->vma);
 
-
   return true;
 }
 
@@ -1144,13 +1147,14 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
                                      sreloc->contents)
                                     + sreloc->reloc_count));
          ++sreloc->reloc_count;
-
+         
          /* If this reloc is against an external symbol, we do not want to
             fiddle with the addend.  Otherwise, we need to include the symbol
             value so that it becomes an addend for the dynamic reloc. */
          if (! relocate)
            return bfd_reloc_ok;
 
+         
          return _bfd_final_link_relocate (howto, input_bfd, input_section,
                                           contents, rel->r_offset, value,
                                           (bfd_vma) 0);
@@ -1164,7 +1168,8 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
          if (sym_flags == STT_ARM_TFUNC)
            {
              elf32_arm_to_thumb_stub (info, sym_name, input_bfd, output_bfd,
-                                      input_section, hit_data, sym_sec, rel->r_offset, addend, value);
+                                      input_section, hit_data, sym_sec, rel->r_offset,
+                                      signed_addend, value);
              return bfd_reloc_ok;
            }
 
@@ -1224,9 +1229,15 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
                }
            }
 
-         value >>= howto->rightshift;
-         value &= howto->dst_mask;
-         value |= (bfd_get_32 (input_bfd, hit_data) & (~ howto->dst_mask));
+         /* Perform a signed range check.  */
+         signed_addend = value;
+         signed_addend >>= howto->rightshift;
+         if (signed_addend > ((bfd_signed_vma)(howto->dst_mask >> 1))
+             || signed_addend < - ((bfd_signed_vma) ((howto->dst_mask + 1) >> 1)))
+           return bfd_reloc_overflow;
+         
+         value = (signed_addend & howto->dst_mask)
+           | (bfd_get_32 (input_bfd, hit_data) & (~ howto->dst_mask));
          break;
 
        case R_ARM_ABS32:
@@ -1300,7 +1311,6 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
        boolean        overflow = false;
        bfd_vma        upper_insn = bfd_get_16 (input_bfd, hit_data);
        bfd_vma        lower_insn = bfd_get_16 (input_bfd, hit_data + 2);
-       bfd_vma        src_mask = 0x007FFFFE;
        bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
        bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
        bfd_vma        check;
@@ -1318,12 +1328,14 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
        }
 #endif
 
-        /* If it's not a call to thumb, assume call to arm */
-       if (sym_flags != STT_ARM_TFUNC)
+        /* If it is not a call to thumb, assume call to arm.
+          If it is a call relative to a section name, then it is not a
+          function call at all, but rather a long jump.  */
+       if (sym_flags != STT_ARM_TFUNC && sym_flags != STT_SECTION)
          {
            if (elf32_thumb_to_arm_stub
                (info, sym_name, input_bfd, output_bfd, input_section,
-                hit_data, sym_sec, rel->r_offset, addend, value))
+                hit_data, sym_sec, rel->r_offset, signed_addend, value))
              return bfd_reloc_ok;
            else
              return bfd_reloc_dangerous;
@@ -1334,11 +1346,11 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
        relocation -= (input_section->output_section->vma
                       + input_section->output_offset
                       + rel->r_offset);
-
+       
        if (! globals->no_pipeline_knowledge)
          {
            Elf_Internal_Ehdr * i_ehdrp; /* Elf file header, internal form */
-
+           
            i_ehdrp = elf_elfheader (input_bfd);
 
            /* Previous versions of this code also used to add in the pipline
@@ -1400,7 +1412,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
       BFD_ASSERT (sgot != NULL);
       if (sgot == NULL)
         return bfd_reloc_notsupported;
-
+      
       /* Note that sgot->output_offset is not involved in this
          calculation.  We always want the start of .got.  If we
          define _GLOBAL_OFFSET_TABLE in a different way, as is
@@ -1505,7 +1517,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
 
          value = sgot->output_offset + off;
        }
-
+      
       return _bfd_final_link_relocate (howto, input_bfd, input_section,
                                       contents, rel->r_offset, value,
                                       (bfd_vma) 0);
@@ -1569,6 +1581,55 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
     }
 }
 
+#ifdef USE_REL
+/* Add INCREMENT to the reloc (of type HOWTO) at ADDRESS.  */
+static void
+arm_add_to_rel (abfd, address, howto, increment)
+     bfd *              abfd;
+     bfd_vma            address;
+     reloc_howto_type * howto;
+     bfd_signed_vma     increment;
+{
+  bfd_vma        contents;
+  bfd_signed_vma addend;
+
+  contents = bfd_get_32 (abfd, address);
+
+  /* Get the (signed) value from the instruction.  */
+  addend = contents & howto->src_mask;
+  if (addend & ((howto->src_mask + 1) >> 1))
+    {
+      bfd_signed_vma mask;
+      
+      mask = -1;
+      mask &= ~ howto->src_mask;
+      addend |= mask;
+    }
+
+  /* Add in the increment, (which is a byte value).  */
+  switch (howto->type)
+    {
+    case R_ARM_THM_PC22:
+    default:
+      addend += increment;
+      break;
+      
+    case R_ARM_PC24:
+      addend <<= howto->size;
+      addend +=  increment;
+      
+      /* Should we check for overflow here ?  */
+
+      /* Drop any undesired bits.  */
+      addend >>= howto->rightshift;
+      break;
+    }
+  
+  contents = (contents & ~ howto->dst_mask) | (addend & howto->dst_mask);
+  
+  bfd_put_32 (abfd, contents, address);
+}
+#endif /* USE_REL */
 
 /* Relocate an ARM ELF section.  */
 static boolean
@@ -1629,18 +1690,8 @@ elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
                {
                  sec = local_sections[r_symndx];
 #ifdef USE_REL
-                 {
-                   bfd_vma val;
-                   bfd_vma insn;
-
-                   insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
-                   val = insn + ((sec->output_offset + sym->st_value)
-                                 >> howto->rightshift);
-                   val &= howto->dst_mask;
-                   val |= insn & ~(howto->dst_mask);
-
-                   bfd_put_32 (input_bfd, val, contents + rel->r_offset);
-                 }
+                 arm_add_to_rel (input_bfd, contents + rel->r_offset,
+                                 howto, sec->output_offset + sym->st_value);
 #else
                  rel->r_addend += (sec->output_offset + sym->st_value)
                    >> howto->rightshift;
@@ -1732,6 +1783,8 @@ elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
            }
          else if (h->root.type == bfd_link_hash_undefweak)
            relocation = 0;
+         else if (info->shared && !info->symbolic && !info->no_undefined)
+           relocation = 0;
          else
            {
              if (!((*info->callbacks->undefined_symbol)
@@ -2043,7 +2096,7 @@ elf32_arm_get_symbol_type (elf_sym, type)
 static asection *
 elf32_arm_gc_mark_hook (abfd, info, rel, h, sym)
        bfd *abfd;
-       struct bfd_link_info *info;
+       struct bfd_link_info *info ATTRIBUTE_UNUSED;
        Elf_Internal_Rela *rel;
        struct elf_link_hash_entry *h;
        Elf_Internal_Sym *sym;
@@ -2065,6 +2118,9 @@ elf32_arm_gc_mark_hook (abfd, info, rel, h, sym)
 
           case bfd_link_hash_common:
             return h->root.u.c.p->section;
+
+         default:
+           break;
           }
        }
      }
@@ -2085,10 +2141,10 @@ elf32_arm_gc_mark_hook (abfd, info, rel, h, sym)
 
 static boolean
 elf32_arm_gc_sweep_hook (abfd, info, sec, relocs)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     asection *sec;
-     const Elf_Internal_Rela *relocs;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+     asection *sec ATTRIBUTE_UNUSED;
+     const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
 {
   /* We don't support garbage collection of GOT and PLT relocs yet.  */
   return true;
@@ -2111,12 +2167,12 @@ elf32_arm_check_relocs (abfd, info, sec, relocs)
   bfd *                         dynobj;
   asection * sgot, *srelgot, *sreloc;
   bfd_vma * local_got_offsets;
-
+  
   if (info->relocateable)
     return true;
-
+  
   sgot = srelgot = sreloc = NULL;
-
+  
   dynobj = elf_hash_table (info)->dynobj;
   local_got_offsets = elf_local_got_offsets (abfd);
 
@@ -2125,19 +2181,19 @@ elf32_arm_check_relocs (abfd, info, sec, relocs)
   sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
   if (!elf_bad_symtab (abfd))
     sym_hashes_end -= symtab_hdr->sh_info;
-
+  
   rel_end = relocs + sec->reloc_count;
   for (rel = relocs; rel < rel_end; rel++)
     {
       struct elf_link_hash_entry *h;
       unsigned long r_symndx;
-
+      
       r_symndx = ELF32_R_SYM (rel->r_info);
       if (r_symndx < symtab_hdr->sh_info)
         h = NULL;
       else
         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-
+      
       /* Some relocs require a global offset table.  */
       if (dynobj == NULL)
        {
@@ -2171,7 +2227,7 @@ elf32_arm_check_relocs (abfd, info, sec, relocs)
                && (h != NULL || info->shared))
              {
                srelgot = bfd_get_section_by_name (dynobj, ".rel.got");
-
+               
                /* If no got relocation section, make one and initialize.  */
                if (srelgot == NULL)
                  {
@@ -2356,11 +2412,11 @@ elf32_arm_check_relocs (abfd, info, sec, relocs)
           if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
             return false;
           break;
-
+         
         /* This relocation describes which C++ vtable entries are actually
            used.  Record for later use during GC.  */
         case R_ARM_GNU_VTENTRY:
-          if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+          if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
             return false;
           break;
         }
@@ -2393,7 +2449,7 @@ elf32_arm_find_nearest_line
 
   if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
                                     filename_ptr, functionname_ptr,
-                                    line_ptr))
+                                    line_ptr, 0))
     return true;
 
   if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
@@ -2826,7 +2882,7 @@ elf32_arm_size_dynamic_sections (output_bfd, info)
 static boolean
 elf32_arm_discard_copies (h, ignore)
      struct elf32_arm_link_hash_entry * h;
-     PTR ignore;
+     PTR ignore ATTRIBUTE_UNUSED;
 {
   struct elf32_arm_pcrel_relocs_copied * s;
 
@@ -3105,7 +3161,7 @@ elf32_arm_finish_dynamic_sections (output_bfd, info)
 static void
 elf32_arm_post_process_headers (abfd, link_info)
      bfd * abfd;
-     struct bfd_link_info * link_info;
+     struct bfd_link_info * link_info ATTRIBUTE_UNUSED;
 {
   Elf_Internal_Ehdr * i_ehdrp; /* Elf file header, internal form */
 
@@ -3146,4 +3202,7 @@ elf32_arm_post_process_headers (abfd, link_info)
 #define elf_backend_want_got_plt    1
 #define elf_backend_want_plt_sym    0
 
+#define elf_backend_got_header_size    12
+#define elf_backend_plt_header_size    PLT_ENTRY_SIZE
+
 #include "elf32-target.h"
This page took 0.028851 seconds and 4 git commands to generate.