bfd/
[deliverable/binutils-gdb.git] / bfd / elf32-arm.h
index bcc118808a50d73bbd297e0a85db6851c2eb96f1..6854b7d181b68fe67911c1d7918e9e79ab5051a9 100644 (file)
@@ -1,5 +1,6 @@
 /* 32-bit ELF support for ARM
-   Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -105,7 +106,7 @@ bfd_boolean bfd_elf32_arm_allocate_interworking_sections
 bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
   PARAMS ((bfd *, struct bfd_link_info *));
 bfd_boolean bfd_elf32_arm_process_before_allocation
-  PARAMS ((bfd *, struct bfd_link_info *, int));
+  PARAMS ((bfd *, struct bfd_link_info *, int, int));
 #endif
 
 
@@ -189,6 +190,26 @@ static const bfd_vma elf32_arm_plt_entry [PLT_ENTRY_SIZE / 4] =
 
 #endif
 
+/* Used to build a map of a section.  This is required for mixed-endian
+   code/data.  */
+
+typedef struct elf32_elf_section_map
+{
+  bfd_vma vma;
+  char type;
+}
+elf32_arm_section_map;
+
+struct _arm_elf_section_data
+{
+  struct bfd_elf_section_data elf;
+  int mapcount;
+  elf32_arm_section_map *map;
+};
+
+#define elf32_arm_section_data(sec) \
+  ((struct _arm_elf_section_data *) elf_section_data (sec))
+
 /* The ARM linker needs to keep track of the number of relocs that it
    decides to copy in check_relocs for each symbol.  This is so that
    it can discard PC relative relocs if it doesn't need them when
@@ -205,8 +226,6 @@ struct elf32_arm_relocs_copied
     asection * section;
     /* Number of relocs copied in this section.  */
     bfd_size_type count;
-    /* Number of relocs copied in this section.  */
-    bfd_size_type pc_count;
   };
 
 /* Arm ELF linker hash entry.  */
@@ -235,19 +254,22 @@ struct elf32_arm_link_hash_table
     /* The main hash table.  */
     struct elf_link_hash_table root;
 
-    /* The size in bytes of the section containg the Thumb-to-ARM glue.  */
+    /* The size in bytes of the section containing the Thumb-to-ARM glue.  */
     bfd_size_type thumb_glue_size;
 
-    /* The size in bytes of the section containg the ARM-to-Thumb glue.  */
+    /* The size in bytes of the section containing the ARM-to-Thumb glue.  */
     bfd_size_type arm_glue_size;
 
-    /* An arbitary input BFD chosen to hold the glue sections.  */
+    /* An arbitrary input BFD chosen to hold the glue sections.  */
     bfd * bfd_of_glue_owner;
 
     /* A boolean indicating whether knowledge of the ARM's pipeline
        length should be applied by the linker.  */
     int no_pipeline_knowledge;
 
+    /* Nonzero to output a BE8 image.  */
+    int byteswap_code;
+
     /* Short-cuts to get to dynamic linker sections.  */
     asection *sgot;
     asection *sgotplt;
@@ -383,7 +405,6 @@ elf32_arm_copy_indirect_symbol (const struct elf_backend_data *bed,
              for (q = edir->relocs_copied; q != NULL; q = q->next)
                if (q->section == p->section)
                  {
-                   q->pc_count += p->pc_count;
                    q->count += p->count;
                    *pp = p->next;
                    break;
@@ -432,6 +453,7 @@ elf32_arm_link_hash_table_create (abfd)
   ret->arm_glue_size = 0;
   ret->bfd_of_glue_owner = NULL;
   ret->no_pipeline_knowledge = 0;
+  ret->byteswap_code = 0;
   ret->sym_sec.abfd = NULL;
 
   return &ret->root.root;
@@ -567,7 +589,7 @@ bfd_elf32_arm_allocate_interworking_sections (info)
       foo = (bfd_byte *) bfd_alloc (globals->bfd_of_glue_owner,
                                    globals->arm_glue_size);
 
-      s->_raw_size = s->_cooked_size = globals->arm_glue_size;
+      s->size = globals->arm_glue_size;
       s->contents = foo;
     }
 
@@ -583,7 +605,7 @@ bfd_elf32_arm_allocate_interworking_sections (info)
       foo = (bfd_byte *) bfd_alloc (globals->bfd_of_glue_owner,
                                    globals->thumb_glue_size);
 
-      s->_raw_size = s->_cooked_size = globals->thumb_glue_size;
+      s->size = globals->thumb_glue_size;
       s->contents = foo;
     }
 
@@ -810,10 +832,13 @@ bfd_elf32_arm_get_bfd_for_interworking (abfd, info)
 }
 
 bfd_boolean
-bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)
+bfd_elf32_arm_process_before_allocation (abfd, link_info,
+                                        no_pipeline_knowledge,
+                                        byteswap_code)
      bfd *abfd;
      struct bfd_link_info *link_info;
      int no_pipeline_knowledge;
+     int byteswap_code;
 {
   Elf_Internal_Shdr *symtab_hdr;
   Elf_Internal_Rela *internal_relocs = NULL;
@@ -836,6 +861,14 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)
   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
 
   globals->no_pipeline_knowledge = no_pipeline_knowledge;
+  if (byteswap_code && !bfd_big_endian (abfd))
+    {
+      _bfd_error_handler (
+         _("%s: BE8 images only valid in big-endian mode."),
+         bfd_archive_filename (abfd));
+      return FALSE;
+    }
+  globals->byteswap_code = byteswap_code;
 
   /* Rummage around all the relocs and map the glue vectors.  */
   sec = abfd->sections;
@@ -883,12 +916,7 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)
              else
                {
                  /* Go get them off disk.  */
-                 contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
-                 if (contents == NULL)
-                   goto error_return;
-
-                 if (!bfd_get_section_contents (abfd, sec, contents,
-                                                (file_ptr) 0, sec->_raw_size))
+                 if (!bfd_malloc_and_get_section (abfd, sec, &contents))
                    goto error_return;
                }
            }
@@ -965,7 +993,7 @@ error_return:
    instruction.
 
    It takes two thumb instructions to encode the target address. Each has
-   11 bits to invest. The upper 11 bits are stored in one (identifed by
+   11 bits to invest. The upper 11 bits are stored in one (identified by
    H-0.. see below), the lower 11 bits are stored in the other (identified
    by H-1).
 
@@ -1211,18 +1239,6 @@ elf32_arm_to_thumb_stub (info, name, input_bfd, output_bfd, input_section,
   return TRUE;
 }
 
-/* This is the condition under which elf32_arm_finish_dynamic_symbol
-   will be called from elflink.h.  If elflink.h doesn't call our
-   finish_dynamic_symbol routine, we'll need to do something about
-   initializing any .plt and .got entries in elf32_arm_relocate_section
-   and elf32_arm_final_link_relocate.  */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H)                        \
-  ((DYN)                                                               \
-   && ((SHARED)                                                                \
-       || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)     \
-   && ((H)->dynindx != -1                                              \
-       || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
 /* Perform a relocation as part of a final link.  */
 
 static bfd_reloc_status_type
@@ -1307,21 +1323,46 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
 #ifndef OLD_ARM_ABI
     case R_ARM_XPC25:
 #endif
+    case R_ARM_PLT32:
       /* r_symndx will be zero only for relocs against symbols
         from removed linkonce sections, or sections discarded by
         a linker script.  */
       if (r_symndx == 0)
        return bfd_reloc_ok;
 
+      /* Handle relocations which should use the PLT entry.  ABS32/REL32
+        will use the symbol's value, which may point to a PLT entry, but we
+        don't need to handle that here.  If we created a PLT entry, all
+        branches in this object should go to it.  */
+      if ((r_type != R_ARM_ABS32 && r_type != R_ARM_REL32)
+         && h != NULL
+         && splt != NULL
+         && h->plt.offset != (bfd_vma) -1)
+       {
+         /* If we've created a .plt section, and assigned a PLT entry to
+            this function, it should not be known to bind locally.  If
+            it were, we would have cleared the PLT entry.  */
+         BFD_ASSERT (!SYMBOL_CALLS_LOCAL (info, h));
+
+         value = (splt->output_section->vma
+                  + splt->output_offset
+                  + h->plt.offset);
+         return _bfd_final_link_relocate (howto, input_bfd, input_section,
+                                          contents, rel->r_offset, value,
+                                          (bfd_vma) 0);
+       }
+
       /* When generating a shared object, these relocations are copied
         into the output file to be resolved at run time.  */
-      if ((info->shared
-          && (input_section->flags & SEC_ALLOC)
-          && (h == NULL
-              || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-              || h->root.type != bfd_link_hash_undefweak)
-          && (r_type != R_ARM_PC24
-              || !SYMBOL_CALLS_LOCAL (info, h))))
+      if (info->shared
+         && (input_section->flags & SEC_ALLOC)
+         && (r_type != R_ARM_REL32
+             || !SYMBOL_CALLS_LOCAL (info, h))
+         && (h == NULL
+             || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+             || h->root.type != bfd_link_hash_undefweak)
+         && r_type != R_ARM_PC24
+         && r_type != R_ARM_PLT32)
        {
          Elf_Internal_Rela outrel;
          bfd_byte *loc;
@@ -1364,8 +1405,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
            memset (&outrel, 0, sizeof outrel);
          else if (h != NULL
                   && h->dynindx != -1
-                  && (r_type == R_ARM_PC24
-                      || !info->shared
+                  && (!info->shared
                       || !info->symbolic
                       || (h->elf_link_hash_flags
                           & ELF_LINK_HASH_DEF_REGULAR) == 0))
@@ -1397,6 +1437,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
        case R_ARM_XPC25:         /* Arm BLX instruction.  */
 #endif
        case R_ARM_PC24:          /* Arm B/BL instruction */
+       case R_ARM_PLT32:
 #ifndef OLD_ARM_ABI
          if (r_type == R_ARM_XPC25)
            {
@@ -1723,6 +1764,33 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
        return bfd_reloc_ok;
       }
 
+#ifndef OLD_ARM_ABI
+    case R_ARM_ALU_PCREL7_0:
+    case R_ARM_ALU_PCREL15_8:
+    case R_ARM_ALU_PCREL23_15:
+      {
+       bfd_vma insn;
+       bfd_vma relocation;
+
+       insn = bfd_get_32 (input_bfd, hit_data);
+#if USE_REL
+       /* Extract the addend.  */
+       addend = (insn & 0xff) << ((insn & 0xf00) >> 7);
+       signed_addend = addend;
+#endif
+       relocation = value + signed_addend;
+
+       relocation -= (input_section->output_section->vma
+                      + input_section->output_offset
+                      + rel->r_offset);
+       insn = (insn & ~0xfff)
+              | ((howto->bitpos << 7) & 0xf00)
+              | ((relocation >> howto->bitpos) & 0xff);
+       bfd_put_32 (input_bfd, value, hit_data);
+      }
+      return bfd_reloc_ok;
+#endif
+
     case R_ARM_GNU_VTINHERIT:
     case R_ARM_GNU_VTENTRY:
       return bfd_reloc_ok;
@@ -1869,37 +1937,6 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
                                       contents, rel->r_offset, value,
                                       (bfd_vma) 0);
 
-    case R_ARM_PLT32:
-      /* Relocation is to the entry for this symbol in the
-         procedure linkage table.  */
-
-      /* Resolve a PLT32 reloc against a local symbol directly,
-         without using the procedure linkage table.  */
-      if (h == NULL)
-        return _bfd_final_link_relocate (howto, input_bfd, input_section,
-                                contents, rel->r_offset, value,
-                                (bfd_vma) 0);
-
-      if (h->plt.offset == (bfd_vma) -1
-         || globals->splt == NULL)
-        /* We didn't make a PLT entry for this symbol.  This
-           happens when statically linking PIC code, or when
-           using -Bsymbolic.  */
-       return _bfd_final_link_relocate (howto, input_bfd, input_section,
-                                        contents, rel->r_offset, value,
-                                        (bfd_vma) 0);
-
-      BFD_ASSERT(splt != NULL);
-      if (splt == NULL)
-        return bfd_reloc_notsupported;
-
-      value = (splt->output_section->vma
-              + splt->output_offset
-              + h->plt.offset);
-      return _bfd_final_link_relocate (howto, input_bfd, input_section,
-                              contents, rel->r_offset, value,
-                              (bfd_vma) 0);
-
     case R_ARM_SBREL32:
       return bfd_reloc_notsupported;
 
@@ -2135,10 +2172,10 @@ elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
          bfd_boolean warned;
          bfd_boolean unresolved_reloc;
 
-         RELOC_FOR_GLOBAL_SYMBOL (h, sym_hashes, r_symndx,
-                                  symtab_hdr, relocation,
-                                  sec, unresolved_reloc, info,
-                                  warned);
+         RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+                                  r_symndx, symtab_hdr, sym_hashes,
+                                  h, sec, relocation,
+                                  unresolved_reloc, warned);
          
          if (unresolved_reloc || relocation != 0)
            {
@@ -2150,6 +2187,8 @@ elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
                case R_ARM_PC24:
                case R_ARM_ABS32:
                case R_ARM_THM_PC22:
+               case R_ARM_PLT32:
+
                  if (info->shared
                      && (
                          (!info->symbolic && h->dynindx != -1)
@@ -2183,11 +2222,6 @@ elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
                    relocation = 0;
                  break;
 
-               case R_ARM_PLT32:
-                 if (h->plt.offset != (bfd_vma)-1)
-                   relocation = 0;
-                 break;
-
                default:
                  if (unresolved_reloc)
                    _bfd_error_handler
@@ -2441,11 +2475,16 @@ elf32_arm_merge_private_bfd_data (ibfd, obfd)
      not, its flags may not have been initialised either, but it
      cannot actually cause any incompatibility.  Do not short-circuit
      dynamic objects; their section list may be emptied by
-     elf_link_add_object_symbols.  */
+    elf_link_add_object_symbols.
 
+    Also check to see if there are no code sections in the input.
+    In this case there is no need to check for code specific flags.
+    XXX - do we need to worry about floating-point format compatability
+    in data sections ?  */
   if (!(ibfd->flags & DYNAMIC))
     {
       bfd_boolean null_input_bfd = TRUE;
+      bfd_boolean only_data_sections = TRUE;
 
       for (sec = ibfd->sections; sec != NULL; sec = sec->next)
        {
@@ -2453,11 +2492,17 @@ elf32_arm_merge_private_bfd_data (ibfd, obfd)
          if (strcmp (sec->name, ".glue_7")
              && strcmp (sec->name, ".glue_7t"))
            {
+             if ((bfd_get_section_flags (ibfd, sec)
+                  & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
+                 == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
+               only_data_sections = FALSE;
+
              null_input_bfd = FALSE;
              break;
            }
        }
-      if (null_input_bfd)
+
+      if (null_input_bfd || only_data_sections)
        return TRUE;
     }
 
@@ -2610,7 +2655,7 @@ elf32_arm_print_private_bfd_data (abfd, ptr)
   switch (EF_ARM_EABI_VERSION (flags))
     {
     case EF_ARM_EABI_UNKNOWN:
-      /* The following flag bits are GNU extenstions and not part of the
+      /* The following flag bits are GNU extensions and not part of the
         official ARM ELF extended ABI.  Hence they are only decoded if
         the EABI version is not set.  */
       if (flags & EF_ARM_INTERWORK)
@@ -2678,6 +2723,18 @@ elf32_arm_print_private_bfd_data (abfd, ptr)
                 | EF_ARM_MAPSYMSFIRST);
       break;
 
+    case EF_ARM_EABI_VER3:
+      fprintf (file, _(" [Version3 EABI]"));
+
+      if (flags & EF_ARM_BE8)
+       fprintf (file, _(" [BE8]"));
+
+      if (flags & EF_ARM_LE8)
+       fprintf (file, _(" [LE8]"));
+
+      flags &= ~(EF_ARM_LE8 | EF_ARM_BE8);
+      break;
+
     default:
       fprintf (file, _(" <EABI version unrecognised>"));
       break;
@@ -2808,6 +2865,7 @@ elf32_arm_gc_sweep_hook (abfd, info, sec, relocs)
       case R_ARM_ABS32:
       case R_ARM_REL32:
       case R_ARM_PC24:
+      case R_ARM_PLT32:
        r_symndx = ELF32_R_SYM (rel->r_info);
        if (r_symndx >= symtab_hdr->sh_info)
          {
@@ -2817,31 +2875,24 @@ elf32_arm_gc_sweep_hook (abfd, info, sec, relocs)
 
            h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 
-           if (!info->shared && h->plt.refcount > 0)
+           if (h->plt.refcount > 0)
              h->plt.refcount -= 1;
 
-           eh = (struct elf32_arm_link_hash_entry *) h;
-
-           for (pp = &eh->relocs_copied; (p = *pp) != NULL; pp = &p->next)
-             if (p->section == sec)
-               {
-                 if (ELF32_R_TYPE (rel->r_info) == R_ARM_PC24)
-                   p->pc_count -= 1;
-                 p->count -= 1;
-                 if (p->count == 0)
-                   *pp = p->next;
-                 break;
-               }
-         }
-       break;
+           if (ELF32_R_TYPE (rel->r_info) == R_ARM_ABS32
+               || ELF32_R_TYPE (rel->r_info) == R_ARM_REL32)
+             {
+               eh = (struct elf32_arm_link_hash_entry *) h;
 
-      case R_ARM_PLT32:
-       r_symndx = ELF32_R_SYM (rel->r_info);
-       if (r_symndx >= symtab_hdr->sh_info)
-         {
-           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-           if (h->plt.refcount > 0)
-             h->plt.refcount -= 1;
+               for (pp = &eh->relocs_copied; (p = *pp) != NULL;
+                    pp = &p->next)
+               if (p->section == sec)
+                 {
+                   p->count -= 1;
+                   if (p->count == 0)
+                     *pp = p->next;
+                   break;
+                 }
+             }
          }
        break;
 
@@ -2902,23 +2953,6 @@ elf32_arm_check_relocs (abfd, info, sec, relocs)
 
       switch (ELF32_R_TYPE (rel->r_info))
         {
-         case R_ARM_PLT32:
-           /* This symbol requires a procedure linkage table entry.  We
-               actually build the entry in adjust_dynamic_symbol,
-               because this might be a case of linking PIC code which is
-               never referenced by a dynamic object, in which case we
-               don't need to generate a procedure linkage table entry
-               after all.  */
-
-           /* If this is a local symbol, we resolve it directly without
-               creating a procedure linkage table entry.  */
-           if (h == NULL)
-             continue;
-
-           h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
-           h->plt.refcount++;
-           break;
-
          case R_ARM_GOT32:
            /* This symbol requires a global offset table entry.  */
            if (h != NULL)
@@ -2961,7 +2995,8 @@ elf32_arm_check_relocs (abfd, info, sec, relocs)
          case R_ARM_ABS32:
          case R_ARM_REL32:
          case R_ARM_PC24:
-           if (h != NULL && !info->shared)
+         case R_ARM_PLT32:
+           if (h != NULL)
              {
                /* If this reloc is in a read-only section, we might
                   need a copy reloc.  We can't check reliably at this
@@ -2969,10 +3004,19 @@ elf32_arm_check_relocs (abfd, info, sec, relocs)
                   sections have not yet been mapped to output sections.
                   Tentatively set the flag for now, and correct in
                   adjust_dynamic_symbol.  */
-               h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
-               
+               if (!info->shared)
+                 h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
+
                /* We may need a .plt entry if the function this reloc
-                  refers to is in a shared lib.  */
+                  refers to is in a different object.  We can't tell for
+                  sure yet, because something later might force the
+                  symbol local.  */
+               if (ELF32_R_TYPE (rel->r_info) == R_ARM_PC24
+                   || ELF32_R_TYPE (rel->r_info) == R_ARM_PLT32)
+                 h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+
+               /* If we create a PLT entry, this relocation will reference
+                  it, even if it's an ABS32 relocation.  */
                h->plt.refcount += 1;
              }
 
@@ -2990,7 +3034,9 @@ elf32_arm_check_relocs (abfd, info, sec, relocs)
                relocs_copied field of the hash table entry.  */
            if (info->shared
                && (sec->flags & SEC_ALLOC) != 0
-               && (ELF32_R_TYPE (rel->r_info) != R_ARM_PC24
+               && ((ELF32_R_TYPE (rel->r_info) != R_ARM_PC24
+                    && ELF32_R_TYPE (rel->r_info) != R_ARM_PLT32
+                    && ELF32_R_TYPE (rel->r_info) != R_ARM_REL32)
                    || (h != NULL
                        && (! info->symbolic
                            || (h->elf_link_hash_flags
@@ -3068,26 +3114,25 @@ elf32_arm_check_relocs (abfd, info, sec, relocs)
                    *head = p;
                    p->section = sec;
                    p->count = 0;
-                   p->pc_count = 0;
                  }
                
-               p->count += 1;
-               if (ELF32_R_TYPE (rel->r_info) == R_ARM_PC24)
-                 p->pc_count += 1;
+               if (ELF32_R_TYPE (rel->r_info) == R_ARM_ABS32
+                   || ELF32_R_TYPE (rel->r_info) == R_ARM_REL32)
+                 p->count += 1;
              }
            break;
 
         /* This relocation describes the C++ object vtable hierarchy.
            Reconstruct it for later use during GC.  */
         case R_ARM_GNU_VTINHERIT:
-          if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+          if (!bfd_elf_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_offset))
+          if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
             return FALSE;
           break;
         }
@@ -3281,7 +3326,7 @@ elf32_arm_adjust_dynamic_symbol (info, h)
 
       srel = bfd_get_section_by_name (dynobj, ".rel.bss");
       BFD_ASSERT (srel != NULL);
-      srel->_raw_size += sizeof (Elf32_External_Rel);
+      srel->size += sizeof (Elf32_External_Rel);
       h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
     }
 
@@ -3292,8 +3337,7 @@ elf32_arm_adjust_dynamic_symbol (info, h)
     power_of_two = 3;
 
   /* Apply the required alignment.  */
-  s->_raw_size = BFD_ALIGN (s->_raw_size,
-                           (bfd_size_type) (1 << power_of_two));
+  s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
   if (power_of_two > bfd_get_section_alignment (dynobj, s))
     {
       if (! bfd_set_section_alignment (dynobj, s, power_of_two))
@@ -3302,10 +3346,10 @@ elf32_arm_adjust_dynamic_symbol (info, h)
 
   /* Define the symbol as being at this point in the section.  */
   h->root.u.def.section = s;
-  h->root.u.def.value = s->_raw_size;
+  h->root.u.def.value = s->size;
 
   /* Increment the section size to make room for the symbol.  */
-  s->_raw_size += h->size;
+  s->size += h->size;
 
   return TRUE;
 }
@@ -3343,21 +3387,21 @@ allocate_dynrelocs (h, inf)
       if (h->dynindx == -1
          && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
        {
-         if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+         if (! bfd_elf_link_record_dynamic_symbol (info, h))
            return FALSE;
        }
 
       if (info->shared
-         || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
+         || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
        {
          asection *s = htab->splt;
 
          /* If this is the first .plt entry, make room for the special
             first entry.  */
-         if (s->_raw_size == 0)
-           s->_raw_size += PLT_HEADER_SIZE;
+         if (s->size == 0)
+           s->size += PLT_HEADER_SIZE;
 
-         h->plt.offset = s->_raw_size;
+         h->plt.offset = s->size;
 
          /* If this symbol is not defined in a regular file, and we are
             not generating a shared library, then set the symbol to this
@@ -3372,14 +3416,14 @@ allocate_dynrelocs (h, inf)
            }
 
          /* Make room for this entry.  */
-         s->_raw_size += PLT_ENTRY_SIZE;
+         s->size += PLT_ENTRY_SIZE;
 
          /* We also need to make an entry in the .got.plt section, which
             will be placed in the .got section by the linker script.  */
-         htab->sgotplt->_raw_size += 4;
+         htab->sgotplt->size += 4;
 
          /* We also need to make an entry in the .rel.plt section.  */
-         htab->srelplt->_raw_size += sizeof (Elf32_External_Rel);
+         htab->srelplt->size += sizeof (Elf32_External_Rel);
        }
       else
        {
@@ -3403,19 +3447,19 @@ allocate_dynrelocs (h, inf)
       if (h->dynindx == -1
          && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
        {
-         if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+         if (! bfd_elf_link_record_dynamic_symbol (info, h))
            return FALSE;
        }
 
       s = htab->sgot;
-      h->got.offset = s->_raw_size;
-      s->_raw_size += 4;
+      h->got.offset = s->size;
+      s->size += 4;
       dyn = htab->root.dynamic_sections_created;
       if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
           || h->root.type != bfd_link_hash_undefweak)
          && (info->shared
              || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
-       htab->srelgot->_raw_size += sizeof (Elf32_External_Rel);
+       htab->srelgot->size += sizeof (Elf32_External_Rel);
     }
   else
     h->got.offset = (bfd_vma) -1;
@@ -3432,29 +3476,8 @@ allocate_dynrelocs (h, inf)
 
   if (info->shared)
     {
-      /* The only reloc that uses pc_count is R_ARM_PC24, which will
-        appear on a call or on something like ".long foo - .".  We
-        want calls to protected symbols to resolve directly to the
-        function rather than going via the plt.  If people want
-        function pointer comparisons to work as expected then they
-        should avoid writing assembly like ".long foo - .".  */
-      if (SYMBOL_CALLS_LOCAL (info, h))
-       {
-         struct elf32_arm_relocs_copied **pp;
-
-         for (pp = &eh->relocs_copied; (p = *pp) != NULL; )
-           {
-             p->count -= p->pc_count;
-             p->pc_count = 0;
-             if (p->count == 0)
-               *pp = p->next;
-             else
-               pp = &p->next;
-           }
-       }
-
-      /* Also discard relocs on undefined weak syms with non-default
-        visibility.  */
+      /* Discard relocs on undefined weak syms with non-default
+         visibility.  */
       if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
          && h->root.type == bfd_link_hash_undefweak)
        eh->relocs_copied = NULL;
@@ -3477,7 +3500,7 @@ allocate_dynrelocs (h, inf)
          if (h->dynindx == -1
              && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
            {
-             if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+             if (! bfd_elf_link_record_dynamic_symbol (info, h))
                return FALSE;
            }
 
@@ -3496,7 +3519,7 @@ allocate_dynrelocs (h, inf)
   for (p = eh->relocs_copied; p != NULL; p = p->next)
     {
       asection *sreloc = elf_section_data (p->section)->sreloc;
-      sreloc->_raw_size += p->count * sizeof (Elf32_External_Rel);
+      sreloc->size += p->count * sizeof (Elf32_External_Rel);
     }
 
   return TRUE;
@@ -3527,7 +3550,7 @@ elf32_arm_size_dynamic_sections (output_bfd, info)
        {
          s = bfd_get_section_by_name (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
-         s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
+         s->size = sizeof ELF_DYNAMIC_INTERPRETER;
          s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
        }
     }
@@ -3566,7 +3589,7 @@ elf32_arm_size_dynamic_sections (output_bfd, info)
              else if (p->count != 0)
                {
                  srel = elf_section_data (p->section)->sreloc;
-                 srel->_raw_size += p->count * sizeof (Elf32_External_Rel);
+                 srel->size += p->count * sizeof (Elf32_External_Rel);
                  if ((p->section->output_section->flags & SEC_READONLY) != 0)
                    info->flags |= DF_TEXTREL;
                }
@@ -3586,10 +3609,10 @@ elf32_arm_size_dynamic_sections (output_bfd, info)
        {
          if (*local_got > 0)
            {
-             *local_got = s->_raw_size;
-             s->_raw_size += 4;
+             *local_got = s->size;
+             s->size += 4;
              if (info->shared)
-               srel->_raw_size += sizeof (Elf32_External_Rel);
+               srel->size += sizeof (Elf32_External_Rel);
            }
          else
            *local_got = (bfd_vma) -1;
@@ -3621,7 +3644,7 @@ elf32_arm_size_dynamic_sections (output_bfd, info)
 
       if (strcmp (name, ".plt") == 0)
        {
-         if (s->_raw_size == 0)
+         if (s->size == 0)
            {
              /* Strip this section if we don't need it; see the
                  comment below.  */
@@ -3635,7 +3658,7 @@ elf32_arm_size_dynamic_sections (output_bfd, info)
        }
       else if (strncmp (name, ".rel", 4) == 0)
        {
-         if (s->_raw_size == 0)
+         if (s->size == 0)
            {
              /* If we don't need this section, strip it from the
                 output file.  This is mostly to handle .rel.bss and
@@ -3673,8 +3696,8 @@ elf32_arm_size_dynamic_sections (output_bfd, info)
        }
 
       /* Allocate memory for the section contents.  */
-      s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
-      if (s->contents == NULL && s->_raw_size != 0)
+      s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
+      if (s->contents == NULL && s->size != 0)
        return FALSE;
     }
 
@@ -3686,7 +3709,7 @@ elf32_arm_size_dynamic_sections (output_bfd, info)
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (!info->shared)
        {
@@ -3918,7 +3941,7 @@ elf32_arm_finish_dynamic_sections (output_bfd, info)
       BFD_ASSERT (splt != NULL && sdyn != NULL);
 
       dyncon = (Elf32_External_Dyn *) sdyn->contents;
-      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
 
       for (; dyncon < dynconend; dyncon++)
        {
@@ -3948,10 +3971,7 @@ elf32_arm_finish_dynamic_sections (output_bfd, info)
            case DT_PLTRELSZ:
              s = bfd_get_section_by_name (output_bfd, ".rel.plt");
              BFD_ASSERT (s != NULL);
-             if (s->_cooked_size != 0)
-               dyn.d_un.d_val = s->_cooked_size;
-             else
-               dyn.d_un.d_val = s->_raw_size;
+             dyn.d_un.d_val = s->size;
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
 
@@ -3967,12 +3987,7 @@ elf32_arm_finish_dynamic_sections (output_bfd, info)
                 about changing the DT_REL entry.  */
              s = bfd_get_section_by_name (output_bfd, ".rel.plt");
              if (s != NULL)
-               {
-                 if (s->_cooked_size != 0)
-                   dyn.d_un.d_val -= s->_cooked_size;
-                 else
-                   dyn.d_un.d_val -= s->_raw_size;
-               }
+               dyn.d_un.d_val -= s->size;
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
 
@@ -3985,7 +4000,7 @@ elf32_arm_finish_dynamic_sections (output_bfd, info)
              name = info->fini_function;
            get_sym:
              /* If it wasn't set by elf_bfd_final_link
-                then there is nothing to ajdust.  */
+                then there is nothing to adjust.  */
              if (dyn.d_un.d_val != 0)
                {
                  struct elf_link_hash_entry * eh;
@@ -4004,7 +4019,7 @@ elf32_arm_finish_dynamic_sections (output_bfd, info)
        }
 
       /* Fill in the first entry in the procedure linkage table.  */
-      if (splt->_raw_size > 0)
+      if (splt->size > 0)
        {
          bfd_vma got_displacement;
 
@@ -4034,7 +4049,7 @@ elf32_arm_finish_dynamic_sections (output_bfd, info)
     }
 
   /* Fill in the first three entries in the global offset table.  */
-  if (sgot->_raw_size > 0)
+  if (sgot->size > 0)
     {
       if (sdyn == NULL)
        bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
@@ -4057,11 +4072,19 @@ elf32_arm_post_process_headers (abfd, link_info)
      struct bfd_link_info * link_info ATTRIBUTE_UNUSED;
 {
   Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form.  */
+  struct elf32_arm_link_hash_table *globals;
 
   i_ehdrp = elf_elfheader (abfd);
 
   i_ehdrp->e_ident[EI_OSABI]      = ARM_ELF_OS_ABI_VERSION;
   i_ehdrp->e_ident[EI_ABIVERSION] = ARM_ELF_ABI_VERSION;
+
+  if (link_info)
+    {
+      globals = elf32_arm_hash_table (link_info);
+      if (globals->byteswap_code)
+       i_ehdrp->e_flags |= EF_ARM_BE8;
+    }
 }
 
 static enum elf_reloc_type_class
@@ -4081,7 +4104,7 @@ elf32_arm_reloc_type_class (rela)
     }
 }
 
-static bfd_boolean elf32_arm_section_flags           PARAMS ((flagword *, Elf_Internal_Shdr *));
+static bfd_boolean elf32_arm_section_flags           PARAMS ((flagword *, const Elf_Internal_Shdr *));
 static void        elf32_arm_final_write_processing  PARAMS ((bfd *, bfd_boolean));
 
 /* Set the right machine number for an Arm ELF file.  */
@@ -4089,7 +4112,7 @@ static void        elf32_arm_final_write_processing  PARAMS ((bfd *, bfd_boolean
 static bfd_boolean
 elf32_arm_section_flags (flags, hdr)
      flagword *flags;
-     Elf_Internal_Shdr *hdr;
+     const Elf_Internal_Shdr *hdr;
 {
   if (hdr->sh_type == SHT_NOTE)
     *flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_SAME_CONTENTS;
@@ -4097,7 +4120,7 @@ elf32_arm_section_flags (flags, hdr)
   return TRUE;
 }
 
-void
+static void
 elf32_arm_final_write_processing (abfd, linker)
      bfd *abfd;
      bfd_boolean linker ATTRIBUTE_UNUSED;
@@ -4105,6 +4128,148 @@ elf32_arm_final_write_processing (abfd, linker)
   bfd_arm_update_notes (abfd, ARM_NOTE_SECTION);
 }
 
+
+/* Called for each symbol.  Builds a section map based on mapping symbols.
+   Does not alter any of the symbols.  */
+
+static bfd_boolean
+elf32_arm_output_symbol_hook (struct bfd_link_info *info,
+                             const char *name,
+                             Elf_Internal_Sym *elfsym,
+                             asection *input_sec,
+                             struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
+{
+  int mapcount;
+  elf32_arm_section_map *map;
+  struct elf32_arm_link_hash_table *globals;
+
+  /* Only do this on final link.  */
+  if (info->relocatable)
+    return TRUE;
+
+  /* Only build a map if we need to byteswap code.  */
+  globals = elf32_arm_hash_table (info);
+  if (!globals->byteswap_code)
+    return TRUE;
+
+  /* We only want mapping symbols.  */
+  if (name == NULL
+      || name[0] != '$'
+      || (name[1] != 'a'
+         && name[1] != 't'
+         && name[1] != 'd'))
+    return TRUE;
+
+  mapcount = ++(elf32_arm_section_data (input_sec)->mapcount);
+  map = elf32_arm_section_data (input_sec)->map;
+  /* TODO: This may be inefficient, but we probably don't usually have many
+     mapping symbols per section.  */
+  map = bfd_realloc (map, mapcount * sizeof (elf32_arm_section_map));
+  elf32_arm_section_data (input_sec)->map = map;
+  
+  map[mapcount - 1].vma = elfsym->st_value;
+  map[mapcount - 1].type = name[1];
+  return TRUE;
+}
+
+
+/* Allocate target specific section data.  */
+
+static bfd_boolean
+elf32_arm_new_section_hook (bfd *abfd, asection *sec)
+{
+  struct _arm_elf_section_data *sdata;
+  bfd_size_type amt = sizeof (*sdata);
+
+  sdata = bfd_zalloc (abfd, amt);
+  if (sdata == NULL)
+    return FALSE;
+  sec->used_by_bfd = sdata;
+
+  return _bfd_elf_new_section_hook (abfd, sec);
+}
+
+
+/* Used to order a list of mapping symbols by address.  */
+
+static int
+elf32_arm_compare_mapping (const void * a, const void * b)
+{
+  return ((const elf32_arm_section_map *) a)->vma
+        > ((const elf32_arm_section_map *) b)->vma;
+}
+
+
+/* Do code byteswapping.  Return FALSE afterwards so that the section is
+   written out as normal.  */
+
+static bfd_boolean
+elf32_arm_write_section (bfd *output_bfd ATTRIBUTE_UNUSED, asection *sec,
+                        bfd_byte *contents)
+{
+  int mapcount;
+  elf32_arm_section_map *map;
+  bfd_vma ptr;
+  bfd_vma end;
+  bfd_vma offset;
+  bfd_byte tmp;
+  int i;
+  
+  mapcount = elf32_arm_section_data (sec)->mapcount;
+  map = elf32_arm_section_data (sec)->map;
+
+  if (mapcount == 0)
+    return FALSE;
+
+  qsort (map, mapcount, sizeof (elf32_arm_section_map),
+        elf32_arm_compare_mapping);
+
+  offset = sec->output_section->vma + sec->output_offset;
+  ptr = map[0].vma - offset;
+  for (i = 0; i < mapcount; i++)
+    {
+      if (i == mapcount - 1)
+       end = sec->size;
+      else
+       end = map[i + 1].vma - offset;
+      
+      switch (map[i].type)
+       {
+       case 'a':
+         /* Byte swap code words.  */
+         while (ptr + 3 < end)
+           {
+             tmp = contents[ptr];
+             contents[ptr] = contents[ptr + 3];
+             contents[ptr + 3] = tmp;
+             tmp = contents[ptr + 1];
+             contents[ptr + 1] = contents[ptr + 2];
+             contents[ptr + 2] = tmp;
+             ptr += 4;
+           }
+         break;
+
+       case 't':
+         /* Byte swap code halfwords.  */
+         while (ptr + 1 < end)
+           {
+             tmp = contents[ptr];
+             contents[ptr] = contents[ptr + 1];
+             contents[ptr + 1] = tmp;
+             ptr += 2;
+           }
+         break;
+
+       case 'd':
+         /* Leave data alone.  */
+         break;
+       }
+      ptr = end;
+    }
+  free (map);
+  return FALSE;
+}
+
 #define ELF_ARCH                       bfd_arch_arm
 #define ELF_MACHINE_CODE               EM_ARM
 #ifdef __QNXTARGET__
@@ -4120,16 +4285,19 @@ elf32_arm_final_write_processing (abfd, linker)
 #define bfd_elf32_bfd_link_hash_table_create    elf32_arm_link_hash_table_create
 #define bfd_elf32_bfd_reloc_type_lookup                elf32_arm_reloc_type_lookup
 #define bfd_elf32_find_nearest_line            elf32_arm_find_nearest_line
+#define bfd_elf32_new_section_hook             elf32_arm_new_section_hook
 
 #define elf_backend_get_symbol_type             elf32_arm_get_symbol_type
 #define elf_backend_gc_mark_hook                elf32_arm_gc_mark_hook
 #define elf_backend_gc_sweep_hook               elf32_arm_gc_sweep_hook
 #define elf_backend_check_relocs                elf32_arm_check_relocs
 #define elf_backend_relocate_section           elf32_arm_relocate_section
+#define elf_backend_write_section              elf32_arm_write_section
 #define elf_backend_adjust_dynamic_symbol      elf32_arm_adjust_dynamic_symbol
 #define elf_backend_create_dynamic_sections     elf32_arm_create_dynamic_sections
 #define elf_backend_finish_dynamic_symbol      elf32_arm_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_sections    elf32_arm_finish_dynamic_sections
+#define elf_backend_link_output_symbol_hook    elf32_arm_output_symbol_hook
 #define elf_backend_size_dynamic_sections      elf32_arm_size_dynamic_sections
 #define elf_backend_post_process_headers       elf32_arm_post_process_headers
 #define elf_backend_reloc_type_class           elf32_arm_reloc_type_class
This page took 0.038608 seconds and 4 git commands to generate.