* m16.igen (break): Call SignalException not sim_engine_halt.
[deliverable/binutils-gdb.git] / bfd / elfcode.h
index 378d0afd3a7c41ec970ae446c7835dfdea3c07e4..92bb3367e5647a4c0ce41a96189da0274935423a 100644 (file)
@@ -1,5 +1,6 @@
 /* ELF executable support for BFD.
-   Copyright 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+   Copyright 1991, 92, 93, 94, 95, 96, 97, 98, 1999, 2000 Free
+   Software Foundation, Inc.
 
    Written by Fred Fish @ Cygnus Support, from information published
    in "UNIX System V Release 4, Programmers Guide: ANSI C and
@@ -63,7 +64,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
        it's cast in stone.
  */
 
-#include <string.h>            /* For strrchr and friends */
 #include "bfd.h"
 #include "sysdep.h"
 #include "bfdlink.h"
@@ -100,6 +100,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define elf_swap_dyn_out               NAME(bfd_elf,swap_dyn_out)
 #define elf_get_reloc_upper_bound      NAME(bfd_elf,get_reloc_upper_bound)
 #define elf_canonicalize_reloc         NAME(bfd_elf,canonicalize_reloc)
+#define elf_slurp_symbol_table         NAME(bfd_elf,slurp_symbol_table)
 #define elf_get_symtab                 NAME(bfd_elf,get_symtab)
 #define elf_canonicalize_dynamic_symtab \
   NAME(bfd_elf,canonicalize_dynamic_symtab)
@@ -115,10 +116,24 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define elf_find_section               NAME(bfd_elf,find_section)
 #define elf_bfd_link_add_symbols       NAME(bfd_elf,bfd_link_add_symbols)
 #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)
@@ -137,25 +152,26 @@ 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 *));
+static void elf_swap_ehdr_out
+  PARAMS ((bfd *, const Elf_Internal_Ehdr *, Elf_External_Ehdr *));
+static void elf_swap_shdr_in
+  PARAMS ((bfd *, const Elf_External_Shdr *, Elf_Internal_Shdr *));
+static void elf_swap_shdr_out
+  PARAMS ((bfd *, const Elf_Internal_Shdr *, Elf_External_Shdr *));
 
 #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 long elf_slurp_symbol_table PARAMS ((bfd *, asymbol **, boolean));
-
-static boolean elf_slurp_reloc_table PARAMS ((bfd *, asection *, asymbol **));
-
- int _bfd_elf_symbol_from_bfd_symbol PARAMS ((bfd *,
-                                            struct symbol_cache_entry **));
 
-static void write_relocs PARAMS ((bfd *, asection *, PTR));
+static boolean elf_slurp_reloc_table_from_section
+  PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, bfd_size_type,
+          arelent *, asymbol **, boolean));
 
- 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 *));
@@ -169,11 +185,15 @@ 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
@@ -182,11 +202,16 @@ static char *elf_symbol_flags PARAMS ((flagword));
 void
 elf_swap_symbol_in (abfd, src, dst)
      bfd *abfd;
-     Elf_External_Sym *src;
+     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);
@@ -199,7 +224,7 @@ elf_swap_symbol_in (abfd, src, dst)
 void
 elf_swap_symbol_out (abfd, src, cdst)
      bfd *abfd;
-     Elf_Internal_Sym *src;
+     const Elf_Internal_Sym *src;
      PTR cdst;
 {
   Elf_External_Sym *dst = (Elf_External_Sym *) cdst;
@@ -218,14 +243,18 @@ elf_swap_symbol_out (abfd, src, cdst)
 static void
 elf_swap_ehdr_in (abfd, src, dst)
      bfd *abfd;
-     Elf_External_Ehdr *src;
+     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);
@@ -243,15 +272,19 @@ elf_swap_ehdr_in (abfd, src, dst)
 static void
 elf_swap_ehdr_out (abfd, src, dst)
      bfd *abfd;
-     Elf_Internal_Ehdr *src;
+     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... */
   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);
@@ -270,13 +303,18 @@ elf_swap_ehdr_out (abfd, src, dst)
 static void
 elf_swap_shdr_in (abfd, src, dst)
      bfd *abfd;
-     Elf_External_Shdr *src;
+     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);
@@ -293,7 +331,7 @@ elf_swap_shdr_in (abfd, src, dst)
 static void
 elf_swap_shdr_out (abfd, src, dst)
      bfd *abfd;
-     Elf_Internal_Shdr *src;
+     const Elf_Internal_Shdr *src;
      Elf_External_Shdr *dst;
 {
   /* note that all elements of dst are *arrays of unsigned char* already... */
@@ -316,14 +354,24 @@ elf_swap_shdr_out (abfd, src, dst)
 void
 elf_swap_phdr_in (abfd, src, dst)
      bfd *abfd;
-     Elf_External_Phdr *src;
+     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);
@@ -332,7 +380,7 @@ elf_swap_phdr_in (abfd, src, dst)
 void
 elf_swap_phdr_out (abfd, src, dst)
      bfd *abfd;
-     Elf_Internal_Phdr *src;
+     const Elf_Internal_Phdr *src;
      Elf_External_Phdr *dst;
 {
   /* note that all elements of dst are *arrays of unsigned char* already... */
@@ -350,7 +398,7 @@ elf_swap_phdr_out (abfd, src, dst)
 INLINE void
 elf_swap_reloc_in (abfd, src, dst)
      bfd *abfd;
-     Elf_External_Rel *src;
+     const Elf_External_Rel *src;
      Elf_Internal_Rel *dst;
 {
   dst->r_offset = get_word (abfd, (bfd_byte *) src->r_offset);
@@ -360,19 +408,19 @@ elf_swap_reloc_in (abfd, src, dst)
 INLINE void
 elf_swap_reloca_in (abfd, src, dst)
      bfd *abfd;
-     Elf_External_Rela *src;
+     const Elf_External_Rela *src;
      Elf_Internal_Rela *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. */
 INLINE void
 elf_swap_reloc_out (abfd, src, dst)
      bfd *abfd;
-     Elf_Internal_Rel *src;
+     const Elf_Internal_Rel *src;
      Elf_External_Rel *dst;
 {
   put_word (abfd, src->r_offset, dst->r_offset);
@@ -382,12 +430,12 @@ elf_swap_reloc_out (abfd, src, dst)
 INLINE void
 elf_swap_reloca_out (abfd, src, dst)
      bfd *abfd;
-     Elf_Internal_Rela *src;
+     const Elf_Internal_Rela *src;
      Elf_External_Rela *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
@@ -403,11 +451,13 @@ 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);
 }
@@ -451,6 +501,7 @@ elf_object_p (abfd)
   struct elf_backend_data *ebd;
   struct elf_obj_tdata *preserved_tdata = elf_tdata (abfd);
   struct elf_obj_tdata *new_tdata = NULL;
+  asection *s;
 
   /* Read in the ELF header in external format.  */
 
@@ -505,6 +556,10 @@ elf_object_p (abfd)
   elf_debug_file (i_ehdrp);
 #endif
 
+  /* 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;
@@ -537,7 +592,11 @@ elf_object_p (abfd)
          if ((*target_ptr)->flavour != bfd_target_elf_flavour)
            continue;
          back = (struct elf_backend_data *) (*target_ptr)->backend_data;
-         if (back->elf_machine_code == i_ehdrp->e_machine)
+         if (back->elf_machine_code == i_ehdrp->e_machine
+             || (back->elf_machine_alt1 != 0
+                 && back->elf_machine_alt1 == i_ehdrp->e_machine)
+             || (back->elf_machine_alt2 != 0
+                 && back->elf_machine_alt2 == i_ehdrp->e_machine))
            {
              /* target_ptr is an ELF backend which matches this
                 object file, so reject the generic ELF target.  */
@@ -555,10 +614,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;
+  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,
@@ -578,6 +641,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)
     {
@@ -641,12 +713,30 @@ 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:
   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);
@@ -658,11 +748,12 @@ got_no_match:
   return (NULL);
 }
 \f
-
 /* ELF .o/exec file writing */
 
-static void
-write_relocs (abfd, sec, data)
+/* Write out the relocs.  */
+
+void
+elf_write_relocs (abfd, sec, data)
      bfd *abfd;
      asection *sec;
      PTR data;
@@ -672,9 +763,9 @@ 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 = 9999999;  /* should always be written before use */
+  int last_sym_idx = 0;
 
   /* If we have already failed, don't do anything.  */
   if (*failedp)
@@ -700,6 +791,16 @@ write_relocs (abfd, sec, data)
       return;
     }
 
+  /* 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)
     {
@@ -727,11 +828,28 @@ 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;
-             last_sym_idx = n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
+             n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
+             if (n < 0)
+               {
+                 *failedp = true;
+                 return;
+               }
+             last_sym_idx = n;
            }
+
+         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;
+           }
+
          dst_rela.r_info = ELF_R_INFO (n, ptr->howto->type);
 
          dst_rela.r_addend = ptr->addend;
@@ -765,11 +883,28 @@ 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;
-             last_sym_idx = n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
+             n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
+             if (n < 0)
+               {
+                 *failedp = true;
+                 return;
+               }
+             last_sym_idx = n;
+           }
+
+         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;
            }
+
          dst_rel.r_info = ELF_R_INFO (n, ptr->howto->type);
 
          elf_swap_reloc_out (abfd, &dst_rel, src_rel);
@@ -777,10 +912,12 @@ write_relocs (abfd, sec, data)
     }
 }
 
-static int
-write_out_phdrs (abfd, phdr, count)
+/* Write out the program headers.  */
+
+int
+elf_write_out_phdrs (abfd, phdr, count)
      bfd *abfd;
-     Elf_Internal_Phdr *phdr;
+     const Elf_Internal_Phdr *phdr;
      int count;
 {
   while (count--)
@@ -795,8 +932,10 @@ write_out_phdrs (abfd, phdr, count)
   return 0;
 }
 
-static boolean
-write_shdrs_and_ehdr (abfd)
+/* Write out the section headers and the ELF file header.  */
+
+boolean
+elf_write_shdrs_and_ehdr (abfd)
      bfd *abfd;
 {
   Elf_External_Ehdr x_ehdr;    /* Elf file header, external form */
@@ -842,18 +981,20 @@ write_shdrs_and_ehdr (abfd)
   return true;
 }
 
-static long
+long
 elf_slurp_symbol_table (abfd, symptrs, dynamic)
      bfd *abfd;
      asymbol **symptrs;                /* Buffer for generated bfd symbols */
      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
@@ -865,10 +1006,28 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
      space left over at the end.  When we have all the symbols, we
      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;
 
@@ -878,7 +1037,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;
@@ -898,6 +1057,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++)
        {
@@ -946,7 +1136,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))
            {
@@ -974,11 +1167,22 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
            case STT_FUNC:
              sym->symbol.flags |= BSF_FUNCTION;
              break;
+           case STT_OBJECT:
+             sym->symbol.flags |= BSF_OBJECT;
+             break;
            }
 
          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);
@@ -1015,63 +1219,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;
@@ -1089,8 +1287,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;
@@ -1119,8 +1318,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);
 
@@ -1132,6 +1329,82 @@ 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)
@@ -1260,14 +1533,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,
-  write_out_phdrs,
-  write_shdrs_and_ehdr,
-  write_relocs,
+  elf_write_out_phdrs,
+  elf_write_shdrs_and_ehdr,
+  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.034129 seconds and 4 git commands to generate.