Update copyright notices
[deliverable/binutils-gdb.git] / bfd / elfcode.h
index 405e79f6ce8970bb00cc7e1de800bd181b48c1b5..4984896d65db2694808dfef17bbe44300edb15aa 100644 (file)
@@ -1,5 +1,6 @@
 /* ELF executable support for BFD.
-   Copyright 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+   2001 Free Software Foundation, Inc.
 
    Written by Fred Fish @ Cygnus Support, from information published
    in "UNIX System V Release 4, Programmers Guide: ANSI C and
@@ -117,12 +118,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define elf_add_dynamic_entry          NAME(bfd_elf,add_dynamic_entry)
 #define elf_write_shdrs_and_ehdr       NAME(bfd_elf,write_shdrs_and_ehdr)
 #define elf_write_out_phdrs            NAME(bfd_elf,write_out_phdrs)
+#define elf_write_relocs               NAME(bfd_elf,write_relocs)
+#define elf_slurp_reloc_table          NAME(bfd_elf,slurp_reloc_table)
 #define elf_link_create_dynamic_sections \
   NAME(bfd_elf,link_create_dynamic_sections)
 #define elf_link_record_dynamic_symbol  _bfd_elf_link_record_dynamic_symbol
 #define elf_bfd_final_link             NAME(bfd_elf,bfd_final_link)
 #define elf_create_pointer_linker_section NAME(bfd_elf,create_pointer_linker_section)
 #define elf_finish_pointer_linker_section NAME(bfd_elf,finish_pointer_linker_section)
+#define elf_gc_sections                        NAME(_bfd_elf,gc_sections)
+#define elf_gc_common_finalize_got_offsets \
+  NAME(_bfd_elf,gc_common_finalize_got_offsets)
+#define elf_gc_common_final_link       NAME(_bfd_elf,gc_common_final_link)
+#define elf_gc_record_vtinherit                NAME(_bfd_elf,gc_record_vtinherit)
+#define elf_gc_record_vtentry          NAME(_bfd_elf,gc_record_vtentry)
+#define elf_link_record_local_dynamic_symbol \
+  NAME(_bfd_elf,link_record_local_dynamic_symbol)
 
 #if ARCH_SIZE == 64
 #define ELF_R_INFO(X,Y)        ELF64_R_INFO(X,Y)
@@ -141,7 +152,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define LOG_FILE_ALIGN 2
 #endif
 
-/* Forward declarations of static functions */
+/* Static functions */
 
 static void elf_swap_ehdr_in
   PARAMS ((bfd *, const Elf_External_Ehdr *, Elf_Internal_Ehdr *));
@@ -154,20 +165,13 @@ static void elf_swap_shdr_out
 
 #define elf_stringtab_init _bfd_elf_stringtab_init
 
-extern struct bfd_strtab_hash *_bfd_elf_stringtab_init PARAMS ((void));
 #define section_from_elf_index bfd_section_from_elf_index
-extern boolean bfd_section_from_phdr PARAMS ((bfd *, Elf_Internal_Phdr *,
-                                             int));
 
-static boolean elf_slurp_reloc_table PARAMS ((bfd *, asection *, asymbol **));
+static boolean elf_slurp_reloc_table_from_section
+  PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, bfd_size_type,
+          arelent *, asymbol **, boolean));
 
- int _bfd_elf_symbol_from_bfd_symbol PARAMS ((bfd *,
-                                            struct symbol_cache_entry **));
-
-static boolean validate_reloc PARAMS ((bfd *, arelent *));
-static void write_relocs PARAMS ((bfd *, asection *, PTR));
-
- boolean bfd_section_from_shdr PARAMS ((bfd *, unsigned int shindex));
+static boolean elf_file_p PARAMS ((Elf_External_Ehdr *));
 
 #ifdef DEBUG
 static void elf_debug_section PARAMS ((int, Elf_Internal_Shdr *));
@@ -181,15 +185,19 @@ static char *elf_symbol_flags PARAMS ((flagword));
    can be handled by explicitly specifying 32 bits or "the long type".  */
 #if ARCH_SIZE == 64
 #define put_word       bfd_h_put_64
+#define put_signed_word        bfd_h_put_signed_64
 #define get_word       bfd_h_get_64
+#define get_signed_word        bfd_h_get_signed_64
 #endif
 #if ARCH_SIZE == 32
 #define put_word       bfd_h_put_32
+#define put_signed_word        bfd_h_put_signed_32
 #define get_word       bfd_h_get_32
+#define get_signed_word        bfd_h_get_signed_32
 #endif
 
 /* Translate an ELF symbol in external format into an ELF symbol in internal
-   format. */
+   format.  */
 
 void
 elf_swap_symbol_in (abfd, src, dst)
@@ -197,8 +205,13 @@ elf_swap_symbol_in (abfd, src, dst)
      const Elf_External_Sym *src;
      Elf_Internal_Sym *dst;
 {
+  int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
+
   dst->st_name = bfd_h_get_32 (abfd, (bfd_byte *) src->st_name);
-  dst->st_value = get_word (abfd, (bfd_byte *) src->st_value);
+  if (signed_vma)
+    dst->st_value = get_signed_word (abfd, (bfd_byte *) src->st_value);
+  else
+    dst->st_value = get_word (abfd, (bfd_byte *) src->st_value);
   dst->st_size = get_word (abfd, (bfd_byte *) src->st_size);
   dst->st_info = bfd_h_get_8 (abfd, (bfd_byte *) src->st_info);
   dst->st_other = bfd_h_get_8 (abfd, (bfd_byte *) src->st_other);
@@ -206,7 +219,7 @@ elf_swap_symbol_in (abfd, src, dst)
 }
 
 /* Translate an ELF symbol in internal format into an ELF symbol in external
-   format. */
+   format.  */
 
 void
 elf_swap_symbol_out (abfd, src, cdst)
@@ -223,9 +236,8 @@ elf_swap_symbol_out (abfd, src, cdst)
   bfd_h_put_16 (abfd, src->st_shndx, dst->st_shndx);
 }
 
-
 /* Translate an ELF file header in external format into an ELF file header in
-   internal format. */
+   internal format.  */
 
 static void
 elf_swap_ehdr_in (abfd, src, dst)
@@ -233,11 +245,15 @@ elf_swap_ehdr_in (abfd, src, dst)
      const Elf_External_Ehdr *src;
      Elf_Internal_Ehdr *dst;
 {
+  int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
   memcpy (dst->e_ident, src->e_ident, EI_NIDENT);
   dst->e_type = bfd_h_get_16 (abfd, (bfd_byte *) src->e_type);
   dst->e_machine = bfd_h_get_16 (abfd, (bfd_byte *) src->e_machine);
   dst->e_version = bfd_h_get_32 (abfd, (bfd_byte *) src->e_version);
-  dst->e_entry = get_word (abfd, (bfd_byte *) src->e_entry);
+  if (signed_vma)
+    dst->e_entry = get_signed_word (abfd, (bfd_byte *) src->e_entry);
+  else
+    dst->e_entry = get_word (abfd, (bfd_byte *) src->e_entry);
   dst->e_phoff = get_word (abfd, (bfd_byte *) src->e_phoff);
   dst->e_shoff = get_word (abfd, (bfd_byte *) src->e_shoff);
   dst->e_flags = bfd_h_get_32 (abfd, (bfd_byte *) src->e_flags);
@@ -250,7 +266,7 @@ elf_swap_ehdr_in (abfd, src, dst)
 }
 
 /* Translate an ELF file header in internal format into an ELF file header in
-   external format. */
+   external format.  */
 
 static void
 elf_swap_ehdr_out (abfd, src, dst)
@@ -258,12 +274,16 @@ elf_swap_ehdr_out (abfd, src, dst)
      const Elf_Internal_Ehdr *src;
      Elf_External_Ehdr *dst;
 {
+  int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
   memcpy (dst->e_ident, src->e_ident, EI_NIDENT);
-  /* note that all elements of dst are *arrays of unsigned char* already... */
+  /* note that all elements of dst are *arrays of unsigned char* already...  */
   bfd_h_put_16 (abfd, src->e_type, dst->e_type);
   bfd_h_put_16 (abfd, src->e_machine, dst->e_machine);
   bfd_h_put_32 (abfd, src->e_version, dst->e_version);
-  put_word (abfd, src->e_entry, dst->e_entry);
+  if (signed_vma)
+    put_signed_word (abfd, src->e_entry, dst->e_entry);
+  else
+    put_word (abfd, src->e_entry, dst->e_entry);
   put_word (abfd, src->e_phoff, dst->e_phoff);
   put_word (abfd, src->e_shoff, dst->e_shoff);
   bfd_h_put_32 (abfd, src->e_flags, dst->e_flags);
@@ -275,9 +295,8 @@ elf_swap_ehdr_out (abfd, src, dst)
   bfd_h_put_16 (abfd, src->e_shstrndx, dst->e_shstrndx);
 }
 
-
 /* Translate an ELF section header table entry in external format into an
-   ELF section header table entry in internal format. */
+   ELF section header table entry in internal format.  */
 
 static void
 elf_swap_shdr_in (abfd, src, dst)
@@ -285,10 +304,15 @@ elf_swap_shdr_in (abfd, src, dst)
      const Elf_External_Shdr *src;
      Elf_Internal_Shdr *dst;
 {
+  int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
+
   dst->sh_name = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_name);
   dst->sh_type = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_type);
   dst->sh_flags = get_word (abfd, (bfd_byte *) src->sh_flags);
-  dst->sh_addr = get_word (abfd, (bfd_byte *) src->sh_addr);
+  if (signed_vma)
+    dst->sh_addr = get_signed_word (abfd, (bfd_byte *) src->sh_addr);
+  else
+    dst->sh_addr = get_word (abfd, (bfd_byte *) src->sh_addr);
   dst->sh_offset = get_word (abfd, (bfd_byte *) src->sh_offset);
   dst->sh_size = get_word (abfd, (bfd_byte *) src->sh_size);
   dst->sh_link = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_link);
@@ -300,7 +324,7 @@ elf_swap_shdr_in (abfd, src, dst)
 }
 
 /* Translate an ELF section header table entry in internal format into an
-   ELF section header table entry in external format. */
+   ELF section header table entry in external format.  */
 
 static void
 elf_swap_shdr_out (abfd, src, dst)
@@ -308,7 +332,7 @@ elf_swap_shdr_out (abfd, src, dst)
      const Elf_Internal_Shdr *src;
      Elf_External_Shdr *dst;
 {
-  /* note that all elements of dst are *arrays of unsigned char* already... */
+  /* note that all elements of dst are *arrays of unsigned char* already...  */
   bfd_h_put_32 (abfd, src->sh_name, dst->sh_name);
   bfd_h_put_32 (abfd, src->sh_type, dst->sh_type);
   put_word (abfd, src->sh_flags, dst->sh_flags);
@@ -321,9 +345,8 @@ elf_swap_shdr_out (abfd, src, dst)
   put_word (abfd, src->sh_entsize, dst->sh_entsize);
 }
 
-
 /* Translate an ELF program header table entry in external format into an
-   ELF program header table entry in internal format. */
+   ELF program header table entry in internal format.  */
 
 void
 elf_swap_phdr_in (abfd, src, dst)
@@ -331,11 +354,21 @@ elf_swap_phdr_in (abfd, src, dst)
      const Elf_External_Phdr *src;
      Elf_Internal_Phdr *dst;
 {
+  int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
+
   dst->p_type = bfd_h_get_32 (abfd, (bfd_byte *) src->p_type);
   dst->p_flags = bfd_h_get_32 (abfd, (bfd_byte *) src->p_flags);
   dst->p_offset = get_word (abfd, (bfd_byte *) src->p_offset);
-  dst->p_vaddr = get_word (abfd, (bfd_byte *) src->p_vaddr);
-  dst->p_paddr = get_word (abfd, (bfd_byte *) src->p_paddr);
+  if (signed_vma)
+    {
+      dst->p_vaddr = get_signed_word (abfd, (bfd_byte *) src->p_vaddr);
+      dst->p_paddr = get_signed_word (abfd, (bfd_byte *) src->p_paddr);
+    }
+  else
+    {
+      dst->p_vaddr = get_word (abfd, (bfd_byte *) src->p_vaddr);
+      dst->p_paddr = get_word (abfd, (bfd_byte *) src->p_paddr);
+    }
   dst->p_filesz = get_word (abfd, (bfd_byte *) src->p_filesz);
   dst->p_memsz = get_word (abfd, (bfd_byte *) src->p_memsz);
   dst->p_align = get_word (abfd, (bfd_byte *) src->p_align);
@@ -347,7 +380,7 @@ elf_swap_phdr_out (abfd, src, dst)
      const Elf_Internal_Phdr *src;
      Elf_External_Phdr *dst;
 {
-  /* note that all elements of dst are *arrays of unsigned char* already... */
+  /* note that all elements of dst are *arrays of unsigned char* already...  */
   bfd_h_put_32 (abfd, src->p_type, dst->p_type);
   put_word (abfd, src->p_offset, dst->p_offset);
   put_word (abfd, src->p_vaddr, dst->p_vaddr);
@@ -358,7 +391,7 @@ elf_swap_phdr_out (abfd, src, dst)
   put_word (abfd, src->p_align, dst->p_align);
 }
 
-/* Translate an ELF reloc from external format to internal format. */
+/* Translate an ELF reloc from external format to internal format.  */
 INLINE void
 elf_swap_reloc_in (abfd, src, dst)
      bfd *abfd;
@@ -377,10 +410,10 @@ elf_swap_reloca_in (abfd, src, dst)
 {
   dst->r_offset = get_word (abfd, (bfd_byte *) src->r_offset);
   dst->r_info = get_word (abfd, (bfd_byte *) src->r_info);
-  dst->r_addend = get_word (abfd, (bfd_byte *) src->r_addend);
+  dst->r_addend = get_signed_word (abfd, (bfd_byte *) src->r_addend);
 }
 
-/* Translate an ELF reloc from internal format to external format. */
+/* Translate an ELF reloc from internal format to external format.  */
 INLINE void
 elf_swap_reloc_out (abfd, src, dst)
      bfd *abfd;
@@ -399,7 +432,7 @@ elf_swap_reloca_out (abfd, src, dst)
 {
   put_word (abfd, src->r_offset, dst->r_offset);
   put_word (abfd, src->r_info, dst->r_info);
-  put_word (abfd, src->r_addend, dst->r_addend);
+  put_signed_word (abfd, src->r_addend, dst->r_addend);
 }
 
 INLINE void
@@ -415,18 +448,19 @@ elf_swap_dyn_in (abfd, p, dst)
 }
 
 INLINE void
-elf_swap_dyn_out (abfd, src, dst)
+elf_swap_dyn_out (abfd, src, p)
      bfd *abfd;
      const Elf_Internal_Dyn *src;
-     Elf_External_Dyn *dst;
+     PTR p;
 {
+  Elf_External_Dyn *dst = (Elf_External_Dyn *) p;
+
   put_word (abfd, src->d_tag, dst->d_tag);
   put_word (abfd, src->d_un.d_val, dst->d_un.d_val);
 }
 \f
 /* ELF .o/exec file reading */
 
-
 /* Begin processing a given object.
 
    First we validate the file by reading in the ELF header and checking
@@ -462,7 +496,17 @@ elf_object_p (abfd)
   char *shstrtab;              /* Internal copy of section header stringtab */
   struct elf_backend_data *ebd;
   struct elf_obj_tdata *preserved_tdata = elf_tdata (abfd);
+  struct sec *preserved_sections = abfd->sections;
+  unsigned int preserved_section_count = abfd->section_count;
+  enum bfd_architecture previous_arch = bfd_get_arch (abfd);
+  unsigned long previous_mach = bfd_get_mach (abfd);
   struct elf_obj_tdata *new_tdata = NULL;
+  asection *s;
+
+  /* Clear section information, since there might be a recognized bfd that
+     we now check if we can replace, and we don't want to append to it.  */
+  abfd->sections = NULL;
+  abfd->section_count = 0;
 
   /* Read in the ELF header in external format.  */
 
@@ -478,7 +522,7 @@ elf_object_p (abfd)
      make use of.  The magic number must match, the address size ('class')
      and byte-swapping must match our XVEC entry, and it must have a
      section header table (FIXME: See comments re sections at top of this
-     file). */
+     file).  */
 
   if ((elf_file_p (&x_ehdr) == false) ||
       (x_ehdr.e_ident[EI_VERSION] != EV_CURRENT) ||
@@ -517,13 +561,17 @@ elf_object_p (abfd)
   elf_debug_file (i_ehdrp);
 #endif
 
-  /* If there is no section header table, we're hosed. */
+  /* Reject ET_CORE (header indicates core file, not object file) */
+  if (i_ehdrp->e_type == ET_CORE)
+    goto got_wrong_format_error;
+
+  /* If there is no section header table, we're hosed.  */
   if (i_ehdrp->e_shoff == 0)
     goto got_wrong_format_error;
 
   /* As a simple sanity check, verify that the what BFD thinks is the
      size of each section header table entry actually matches the size
-     recorded in the file. */
+     recorded in the file.  */
   if (i_ehdrp->e_shentsize != sizeof (x_shdr))
     goto got_wrong_format_error;
 
@@ -571,10 +619,14 @@ elf_object_p (abfd)
     abfd->flags |= D_PAGED;
 
   if (! bfd_default_set_arch_mach (abfd, ebd->arch, 0))
-    goto got_no_match;
+    {
+      /* It's OK if this fails for the generic target.  */
+      if (ebd->elf_machine_code != EM_NONE)
+       goto got_no_match;
+    }
 
-  /* Remember the entry point specified in the ELF file header. */
-  bfd_get_start_address (abfd) = i_ehdrp->e_entry;
+  /* Remember the entry point specified in the ELF file header.  */
+  bfd_set_start_address (abfd, i_ehdrp->e_entry);
 
   /* Allocate space for a copy of the section header table in
      internal form, seek to the section header table in the file,
@@ -594,6 +646,15 @@ elf_object_p (abfd)
        goto got_no_match;
       elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex);
       elf_elfsections (abfd)[shindex] = i_shdrp + shindex;
+
+      /* If the section is loaded, but not page aligned, clear
+         D_PAGED.  */
+      if ((i_shdrp[shindex].sh_flags & SHF_ALLOC) != 0
+         && i_shdrp[shindex].sh_type != SHT_NOBITS
+         && (((i_shdrp[shindex].sh_addr - i_shdrp[shindex].sh_offset)
+              % ebd->maxpagesize)
+             != 0))
+       abfd->flags &= ~D_PAGED;
     }
   if (i_ehdrp->e_shstrndx)
     {
@@ -630,7 +691,7 @@ elf_object_p (abfd)
     }
 
   /* Read in the string table containing the names of the sections.  We
-     will need the base pointer to this table later. */
+     will need the base pointer to this table later.  */
   /* We read this inline now, so that we don't have to go through
      bfd_section_from_shdr with it (since this particular strtab is
      used to find all of the ELF section names.) */
@@ -657,12 +718,40 @@ elf_object_p (abfd)
        goto got_wrong_format_error;
     }
 
+  /* If we have created any reloc sections that are associated with
+     debugging sections, mark the reloc sections as debugging as well.  */
+  for (s = abfd->sections; s != NULL; s = s->next)
+    {
+      if ((elf_section_data (s)->this_hdr.sh_type == SHT_REL
+          || elf_section_data (s)->this_hdr.sh_type == SHT_RELA)
+         && elf_section_data (s)->this_hdr.sh_info > 0)
+       {
+         unsigned long targ_index;
+         asection *targ_sec;
+
+         targ_index = elf_section_data (s)->this_hdr.sh_info;
+         targ_sec = bfd_section_from_elf_index (abfd, targ_index);
+         if (targ_sec != NULL
+             && (targ_sec->flags & SEC_DEBUGGING) != 0)
+           s->flags |= SEC_DEBUGGING;
+       }
+    }
+
   return (abfd->xvec);
 
-got_wrong_format_error:
+ got_wrong_format_error:
+  /* There is way too much undoing of half-known state here.  The caller,
+     bfd_check_format_matches, really shouldn't iterate on live bfd's to
+     check match/no-match like it does.  We have to rely on that a call to
+     bfd_default_set_arch_mach with the previously known mach, undoes what
+     was done by the first bfd_default_set_arch_mach (with mach 0) here.
+     For this to work, only elf-data and the mach may be changed by the
+     target-specific elf_backend_object_p function.  Note that saving the
+     whole bfd here and restoring it would be even worse; the first thing
+     you notice is that the cached bfd file position gets out of sync.  */
+  bfd_default_set_arch_mach (abfd, previous_arch, previous_mach);
   bfd_set_error (bfd_error_wrong_format);
-  goto got_no_match;
-got_no_match:
+ got_no_match:
   if (new_tdata != NULL
       && new_tdata->elf_sect_ptr != NULL)
     bfd_release (abfd, new_tdata->elf_sect_ptr);
@@ -671,113 +760,17 @@ got_no_match:
   if (new_tdata != NULL)
     bfd_release (abfd, new_tdata);
   elf_tdata (abfd) = preserved_tdata;
+  abfd->sections = preserved_sections;
+  abfd->section_count = preserved_section_count;
   return (NULL);
 }
 \f
 /* ELF .o/exec file writing */
 
-/* Try to convert a non-ELF reloc into an ELF one.  */
-
-static boolean
-validate_reloc (abfd, areloc)
-     bfd *abfd;
-     arelent *areloc;
-{
-  /* Check whether we really have an ELF howto. */
-
-  if ((*areloc->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec) 
-    {
-      bfd_reloc_code_real_type code;
-      reloc_howto_type *howto;
-      
-      /* Alien reloc: Try to determine its type to replace it with an
-        equivalent ELF reloc. */
-
-      if (areloc->howto->pc_relative)
-       {
-         switch (areloc->howto->bitsize)
-           {
-           case 8:
-             code = BFD_RELOC_8_PCREL; 
-             break;
-           case 12:
-             code = BFD_RELOC_12_PCREL; 
-             break;
-           case 16:
-             code = BFD_RELOC_16_PCREL; 
-             break;
-           case 24:
-             code = BFD_RELOC_24_PCREL; 
-             break;
-           case 32:
-             code = BFD_RELOC_32_PCREL; 
-             break;
-           case 64:
-             code = BFD_RELOC_64_PCREL; 
-             break;
-           default:
-             goto fail;
-           }
-
-         howto = bfd_reloc_type_lookup (abfd, code);
-
-         if (areloc->howto->pcrel_offset != howto->pcrel_offset)
-           {
-             if (howto->pcrel_offset)
-               areloc->addend += areloc->address;
-             else
-               areloc->addend -= areloc->address; /* addend is unsigned!! */
-           }
-       }
-      else
-       {
-         switch (areloc->howto->bitsize)
-           {
-           case 8:
-             code = BFD_RELOC_8; 
-             break;
-           case 14:
-             code = BFD_RELOC_14; 
-             break;
-           case 16:
-             code = BFD_RELOC_16; 
-             break;
-           case 26:
-             code = BFD_RELOC_26; 
-             break;
-           case 32:
-             code = BFD_RELOC_32; 
-             break;
-           case 64:
-             code = BFD_RELOC_64; 
-             break;
-           default:
-             goto fail;
-           }
-
-         howto = bfd_reloc_type_lookup (abfd, code);
-       }
-
-      if (howto)
-       areloc->howto = howto;
-      else
-       goto fail;
-    }
-
-  return true;
-
- fail:
-  (*_bfd_error_handler)
-    ("%s: unsupported relocation type %s",
-     bfd_get_filename (abfd), areloc->howto->name);
-  bfd_set_error (bfd_error_bad_value);
-  return false;
-}
-
 /* Write out the relocs.  */
 
-static void
-write_relocs (abfd, sec, data)
+void
+elf_write_relocs (abfd, sec, data)
      bfd *abfd;
      asection *sec;
      PTR data;
@@ -787,7 +780,7 @@ write_relocs (abfd, sec, data)
   Elf_External_Rela *outbound_relocas;
   Elf_External_Rel *outbound_relocs;
   unsigned int idx;
-  int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
+  int use_rela_p;
   asymbol *last_sym = 0;
   int last_sym_idx = 0;
 
@@ -815,7 +808,17 @@ write_relocs (abfd, sec, data)
       return;
     }
 
-  /* orelocation has the data, reloc_count has the count... */
+  /* Figure out whether the relocations are RELA or REL relocations.  */
+  if (rela_hdr->sh_type == SHT_RELA)
+    use_rela_p = true;
+  else if (rela_hdr->sh_type == SHT_REL)
+    use_rela_p = false;
+  else
+    /* Every relocation section should be either an SHT_RELA or an
+       SHT_REL section.  */
+    abort ();
+
+  /* orelocation has the data, reloc_count has the count...  */
   if (use_rela_p)
     {
       outbound_relocas = (Elf_External_Rela *) rela_hdr->contents;
@@ -842,6 +845,8 @@ write_relocs (abfd, sec, data)
          sym = *ptr->sym_ptr_ptr;
          if (sym == last_sym)
            n = last_sym_idx;
+         else if (bfd_is_abs_section (sym->section) && sym->value == 0)
+           n = STN_UNDEF;
          else
            {
              last_sym = sym;
@@ -854,8 +859,9 @@ write_relocs (abfd, sec, data)
              last_sym_idx = n;
            }
 
-         if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
-             && ! validate_reloc (abfd, ptr))
+         if ((*ptr->sym_ptr_ptr)->the_bfd != NULL
+             && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
+             && ! _bfd_elf_validate_reloc (abfd, ptr))
            {
              *failedp = true;
              return;
@@ -894,6 +900,8 @@ write_relocs (abfd, sec, data)
 
          if (sym == last_sym)
            n = last_sym_idx;
+         else if (bfd_is_abs_section (sym->section) && sym->value == 0)
+           n = STN_UNDEF;
          else
            {
              last_sym = sym;
@@ -906,8 +914,9 @@ write_relocs (abfd, sec, data)
              last_sym_idx = n;
            }
 
-         if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
-             && ! validate_reloc (abfd, ptr))
+         if ((*ptr->sym_ptr_ptr)->the_bfd != NULL
+             && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
+             && ! _bfd_elf_validate_reloc (abfd, ptr))
            {
              *failedp = true;
              return;
@@ -955,7 +964,7 @@ elf_write_shdrs_and_ehdr (abfd)
   i_ehdrp = elf_elfheader (abfd);
   i_shdrp = elf_elfsections (abfd);
 
-  /* swap the header before spitting it out... */
+  /* swap the header before spitting it out...  */
 
 #if DEBUG & 1
   elf_debug_file (i_ehdrp);
@@ -966,7 +975,7 @@ elf_write_shdrs_and_ehdr (abfd)
          != sizeof (x_ehdr)))
     return false;
 
-  /* at this point we've concocted all the ELF sections... */
+  /* at this point we've concocted all the ELF sections...  */
   x_shdrp = (Elf_External_Shdr *)
     bfd_alloc (abfd, sizeof (*x_shdrp) * (i_ehdrp->e_shnum));
   if (!x_shdrp)
@@ -984,7 +993,7 @@ elf_write_shdrs_and_ehdr (abfd)
          != sizeof (*x_shdrp) * i_ehdrp->e_shnum))
     return false;
 
-  /* need to dump the string table too... */
+  /* need to dump the string table too...  */
 
   return true;
 }
@@ -996,11 +1005,13 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
      boolean dynamic;
 {
   Elf_Internal_Shdr *hdr;
-  long symcount;               /* Number of external ELF symbols */
+  Elf_Internal_Shdr *verhdr;
+  unsigned long symcount;      /* Number of external ELF symbols */
   elf_symbol_type *sym;                /* Pointer to current bfd symbol */
   elf_symbol_type *symbase;    /* Buffer for generated bfd symbols */
   Elf_Internal_Sym i_sym;
   Elf_External_Sym *x_symp = NULL;
+  Elf_External_Versym *x_versymp = NULL;
 
   /* Read each raw ELF symbol, converting from external ELF form to
      internal ELF form, and then using the information to create a
@@ -1010,12 +1021,30 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
      based on a one-to-one mapping of the ELF symbols to canonical
      symbols.  We actually use all the ELF symbols, so there will be no
      space left over at the end.  When we have all the symbols, we
-     build the caller's pointer vector. */
+     build the caller's pointer vector.  */
 
-  if (dynamic)
-    hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+  if (! dynamic)
+    {
+      hdr = &elf_tdata (abfd)->symtab_hdr;
+      verhdr = NULL;
+    }
   else
-    hdr = &elf_tdata (abfd)->symtab_hdr;
+    {
+      hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+      if (elf_dynversym (abfd) == 0)
+       verhdr = NULL;
+      else
+       verhdr = &elf_tdata (abfd)->dynversym_hdr;
+      if ((elf_tdata (abfd)->dynverdef_section != 0
+          && elf_tdata (abfd)->verdef == NULL)
+         || (elf_tdata (abfd)->dynverref_section != 0
+             && elf_tdata (abfd)->verref == NULL))
+       {
+         if (! _bfd_elf_slurp_version_tables (abfd))
+           return -1;
+       }
+    }
+
   if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1)
     return -1;
 
@@ -1025,7 +1054,7 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
     sym = symbase = NULL;
   else
     {
-      long i;
+      unsigned long i;
 
       if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1)
        return -1;
@@ -1045,6 +1074,37 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
       if (bfd_read ((PTR) x_symp, sizeof (Elf_External_Sym), symcount, abfd)
          != symcount * sizeof (Elf_External_Sym))
        goto error_return;
+
+      /* Read the raw ELF version symbol information.  */
+
+      if (verhdr != NULL
+         && verhdr->sh_size / sizeof (Elf_External_Versym) != symcount)
+       {
+         (*_bfd_error_handler)
+           (_("%s: version count (%ld) does not match symbol count (%ld)"),
+            abfd->filename,
+            (long) (verhdr->sh_size / sizeof (Elf_External_Versym)),
+            symcount);
+
+         /* Slurp in the symbols without the version information,
+             since that is more helpful than just quitting.  */
+         verhdr = NULL;
+       }
+
+      if (verhdr != NULL)
+       {
+         if (bfd_seek (abfd, verhdr->sh_offset, SEEK_SET) != 0)
+           goto error_return;
+
+         x_versymp = (Elf_External_Versym *) bfd_malloc (verhdr->sh_size);
+         if (x_versymp == NULL && verhdr->sh_size != 0)
+           goto error_return;
+
+         if (bfd_read ((PTR) x_versymp, 1, verhdr->sh_size, abfd)
+             != verhdr->sh_size)
+           goto error_return;
+       }
+
       /* Skip first symbol, which is a null dummy.  */
       for (i = 1; i < symcount; i++)
        {
@@ -1093,7 +1153,10 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
          else
            sym->symbol.section = bfd_abs_section_ptr;
 
-         sym->symbol.value -= sym->symbol.section->vma;
+         /* If this is a relocateable file, then the symbol value is
+             already section relative.  */
+         if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
+           sym->symbol.value -= sym->symbol.section->vma;
 
          switch (ELF_ST_BIND (i_sym.st_info))
            {
@@ -1129,6 +1192,14 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
          if (dynamic)
            sym->symbol.flags |= BSF_DYNAMIC;
 
+         if (x_versymp != NULL)
+           {
+             Elf_Internal_Versym iversym;
+
+             _bfd_elf_swap_versym_in (abfd, x_versymp + i, &iversym);
+             sym->version = iversym.vs_vers;
+           }
+
          /* Do some backend-specific processing on this symbol.  */
          {
            struct elf_backend_data *ebd = get_elf_backend_data (abfd);
@@ -1165,63 +1236,57 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
       *symptrs = 0;            /* Final null pointer */
     }
 
+  if (x_versymp != NULL)
+    free (x_versymp);
   if (x_symp != NULL)
     free (x_symp);
   return symcount;
 error_return:
+  if (x_versymp != NULL)
+    free (x_versymp);
   if (x_symp != NULL)
     free (x_symp);
   return -1;
 }
 
-/* Read in and swap the external relocs.  */
+/* Read  relocations for ASECT from REL_HDR.  There are RELOC_COUNT of
+   them.  */
 
 static boolean
-elf_slurp_reloc_table (abfd, asect, symbols)
+elf_slurp_reloc_table_from_section (abfd, asect, rel_hdr, reloc_count,
+                                   relents, symbols, dynamic)
      bfd *abfd;
      asection *asect;
+     Elf_Internal_Shdr *rel_hdr;
+     bfd_size_type reloc_count;
+     arelent *relents;
      asymbol **symbols;
+     boolean dynamic;
 {
   struct elf_backend_data * const ebd = get_elf_backend_data (abfd);
-  struct bfd_elf_section_data * const d = elf_section_data (asect);
   PTR allocated = NULL;
   bfd_byte *native_relocs;
-  arelent *relents;
   arelent *relent;
   unsigned int i;
   int entsize;
 
-  if (asect->relocation != NULL
-      || (asect->flags & SEC_RELOC) == 0
-      || asect->reloc_count == 0)
-    return true;
-
-  BFD_ASSERT (asect->rel_filepos == d->rel_hdr.sh_offset
-             && (asect->reloc_count
-                 == d->rel_hdr.sh_size / d->rel_hdr.sh_entsize));
-
-  allocated = (PTR) bfd_malloc ((size_t) d->rel_hdr.sh_size);
+  allocated = (PTR) bfd_malloc ((size_t) rel_hdr->sh_size);
   if (allocated == NULL)
     goto error_return;
 
-  if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0
-      || (bfd_read (allocated, 1, d->rel_hdr.sh_size, abfd)
-         != d->rel_hdr.sh_size))
+  if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
+      || (bfd_read (allocated, 1, rel_hdr->sh_size, abfd)
+         != rel_hdr->sh_size))
     goto error_return;
 
   native_relocs = (bfd_byte *) allocated;
 
-  relents = ((arelent *)
-            bfd_alloc (abfd, asect->reloc_count * sizeof (arelent)));
-  if (relents == NULL)
-    goto error_return;
-
-  entsize = d->rel_hdr.sh_entsize;
+  entsize = rel_hdr->sh_entsize;
   BFD_ASSERT (entsize == sizeof (Elf_External_Rel)
              || entsize == sizeof (Elf_External_Rela));
 
   for (i = 0, relent = relents;
-       i < asect->reloc_count;
+       i < reloc_count;
        i++, relent++, native_relocs += entsize)
     {
       Elf_Internal_Rela rela;
@@ -1239,8 +1304,9 @@ elf_slurp_reloc_table (abfd, asect, symbols)
 
       /* The address of an ELF reloc is section relative for an object
         file, and absolute for an executable file or shared library.
-        The address of a BFD reloc is always section relative.  */
-      if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+        The address of a normal BFD reloc is always section relative,
+        and the address of a dynamic reloc is absolute..  */
+      if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0 || dynamic)
        relent->address = rela.r_offset;
       else
        relent->address = rela.r_offset - asect->vma;
@@ -1269,8 +1335,6 @@ elf_slurp_reloc_table (abfd, asect, symbols)
        (*ebd->elf_info_to_howto_rel) (abfd, relent, &rel);
     }
 
-  asect->relocation = relents;
-
   if (allocated != NULL)
     free (allocated);
 
@@ -1282,6 +1346,81 @@ elf_slurp_reloc_table (abfd, asect, symbols)
   return false;
 }
 
+/* Read in and swap the external relocs.  */
+
+boolean
+elf_slurp_reloc_table (abfd, asect, symbols, dynamic)
+     bfd *abfd;
+     asection *asect;
+     asymbol **symbols;
+     boolean dynamic;
+{
+  struct bfd_elf_section_data * const d = elf_section_data (asect);
+  Elf_Internal_Shdr *rel_hdr;
+  Elf_Internal_Shdr *rel_hdr2;
+  bfd_size_type reloc_count;
+  bfd_size_type reloc_count2;
+  arelent *relents;
+
+  if (asect->relocation != NULL)
+    return true;
+
+  if (! dynamic)
+    {
+      if ((asect->flags & SEC_RELOC) == 0
+         || asect->reloc_count == 0)
+       return true;
+
+      rel_hdr = &d->rel_hdr;
+      reloc_count = rel_hdr->sh_size / rel_hdr->sh_entsize;
+      rel_hdr2 = d->rel_hdr2;
+      reloc_count2 = (rel_hdr2
+                     ? (rel_hdr2->sh_size / rel_hdr2->sh_entsize)
+                     : 0);
+
+      BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2);
+      BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset
+                 || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset));
+
+    }
+  else
+    {
+      /* Note that ASECT->RELOC_COUNT tends not to be accurate in this
+        case because relocations against this section may use the
+        dynamic symbol table, and in that case bfd_section_from_shdr
+        in elf.c does not update the RELOC_COUNT.  */
+      if (asect->_raw_size == 0)
+       return true;
+
+      rel_hdr = &d->this_hdr;
+      reloc_count = rel_hdr->sh_size / rel_hdr->sh_entsize;
+      rel_hdr2 = NULL;
+      reloc_count2 = 0;
+    }
+
+  relents = ((arelent *)
+            bfd_alloc (abfd,
+                       (reloc_count + reloc_count2) * sizeof (arelent)));
+  if (relents == NULL)
+    return false;
+
+  if (!elf_slurp_reloc_table_from_section (abfd, asect,
+                                          rel_hdr, reloc_count,
+                                          relents,
+                                          symbols, dynamic))
+    return false;
+
+  if (rel_hdr2
+      && !elf_slurp_reloc_table_from_section (abfd, asect,
+                                             rel_hdr2, reloc_count2,
+                                             relents + reloc_count,
+                                             symbols, dynamic))
+    return false;
+
+  asect->relocation = relents;
+  return true;
+}
+
 #ifdef DEBUG
 static void
 elf_debug_section (num, hdr)
@@ -1410,14 +1549,20 @@ const struct elf_size_info NAME(_bfd_elf,size_info) = {
   sizeof (Elf_External_Sym),
   sizeof (Elf_External_Dyn),
   sizeof (Elf_External_Note),
-
+  4,
+  1,
   ARCH_SIZE, FILE_ALIGN,
   ELFCLASS, EV_CURRENT,
   elf_write_out_phdrs,
   elf_write_shdrs_and_ehdr,
-  write_relocs,
+  elf_write_relocs,
   elf_swap_symbol_out,
   elf_slurp_reloc_table,
   elf_slurp_symbol_table,
-  elf_swap_dyn_in
+  elf_swap_dyn_in,
+  elf_swap_dyn_out,
+  NULL,
+  NULL,
+  NULL,
+  NULL
 };
This page took 0.036734 seconds and 4 git commands to generate.