* elfcode.h (NAME(bfd_elf,size_dynamic_sections)): Add rpath
[deliverable/binutils-gdb.git] / bfd / elfcode.h
index c6fea5c97a70e0f7707fb51fd425311faf318864..e34951c52b5f6163ee4567bf45fdb736b92acfdb 100644 (file)
@@ -92,6 +92,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define elf_swap_reloca_in             NAME(bfd_elf,swap_reloca_in)
 #define elf_swap_reloc_out             NAME(bfd_elf,swap_reloc_out)
 #define elf_swap_reloca_out            NAME(bfd_elf,swap_reloca_out)
+#define elf_swap_symbol_in             NAME(bfd_elf,swap_symbol_in)
+#define elf_swap_symbol_out            NAME(bfd_elf,swap_symbol_out)
 #define elf_swap_dyn_in                        NAME(bfd_elf,swap_dyn_in)
 #define elf_swap_dyn_out               NAME(bfd_elf,swap_dyn_out)
 #define elf_get_reloc_upper_bound      NAME(bfd_elf,get_reloc_upper_bound)
@@ -143,6 +145,8 @@ static int elf_section_from_bfd_section PARAMS ((bfd *, struct sec *));
 
 static long elf_slurp_symbol_table PARAMS ((bfd *, asymbol **, boolean));
 
+static boolean elf_slurp_reloc_table PARAMS ((bfd *, asection *, asymbol **));
+
 static int elf_symbol_from_bfd_symbol PARAMS ((bfd *,
                                             struct symbol_cache_entry **));
 
@@ -190,7 +194,7 @@ static void elf_debug_file PARAMS ((Elf_Internal_Ehdr *));
 /* Translate an ELF symbol in external format into an ELF symbol in internal
    format. */
 
-static void
+void
 elf_swap_symbol_in (abfd, src, dst)
      bfd *abfd;
      Elf_External_Sym *src;
@@ -207,7 +211,7 @@ elf_swap_symbol_in (abfd, src, dst)
 /* Translate an ELF symbol in internal format into an ELF symbol in external
    format. */
 
-static void
+void
 elf_swap_symbol_out (abfd, src, dst)
      bfd *abfd;
      Elf_Internal_Sym *src;
@@ -962,11 +966,6 @@ 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 this is a .dynamic section, mark the object file as being
-        dynamically linked.  */
-      if (i_shdrp[shindex].sh_type == SHT_DYNAMIC)
-       abfd->flags |= DYNAMIC;
     }
   if (i_ehdrp->e_shstrndx)
     {
@@ -1462,7 +1461,7 @@ sym_is_global (abfd, sym)
 
       return 1;
     }
-  if (sym->section == &bfd_und_section)
+  if (bfd_is_und_section (sym->section))
     return 1;
   if (bfd_is_com_section (sym->section))
     return 1;
@@ -1611,7 +1610,7 @@ elf_compute_section_file_positions (abfd, link_info)
 
   /* Do any elf backend specific processing first.  */
   if (bed->elf_backend_begin_write_processing)
-    (*bed->elf_backend_begin_write_processing) (abfd);
+    (*bed->elf_backend_begin_write_processing) (abfd, link_info);
 
   if (! prep_headers (abfd))
     return false;
@@ -2130,7 +2129,13 @@ prep_headers (abfd)
   for (count = EI_PAD; count < EI_NIDENT; count++)
     i_ehdrp->e_ident[count] = 0;
 
-  i_ehdrp->e_type = (abfd->flags & EXEC_P) ? ET_EXEC : ET_REL;
+  if ((abfd->flags & DYNAMIC) != 0)
+    i_ehdrp->e_type = ET_DYN;
+  else if ((abfd->flags & EXEC_P) != 0)
+    i_ehdrp->e_type = ET_EXEC;
+  else
+    i_ehdrp->e_type = ET_REL;
+
   switch (bfd_get_arch (abfd))
     {
     case bfd_arch_unknown:
@@ -2267,6 +2272,7 @@ swap_out_syms (abfd)
       {
        Elf_Internal_Sym sym;
        bfd_vma value = syms[idx]->value;
+       elf_symbol_type *type_ptr;
 
        if (syms[idx]->flags & BSF_SECTION_SYM)
          /* Section symbols have no names.  */
@@ -2278,21 +2284,21 @@ swap_out_syms (abfd)
              return false;
          }
 
+       type_ptr = elf_symbol_from (abfd, syms[idx]);
+
        if (bfd_is_com_section (syms[idx]->section))
          {
            /* ELF common symbols put the alignment into the `value' field,
               and the size into the `size' field.  This is backwards from
               how BFD handles it, so reverse it here.  */
            sym.st_size = value;
-           /* Should retrieve this from somewhere... */
-           sym.st_value = 16;
+           sym.st_value = type_ptr ? type_ptr->internal_elf_sym.st_value : 16;
            sym.st_shndx = elf_section_from_bfd_section (abfd,
                                                         syms[idx]->section);
          }
        else
          {
            asection *sec = syms[idx]->section;
-           elf_symbol_type *type_ptr;
            int shndx;
 
            if (sec->output_section)
@@ -2302,7 +2308,6 @@ swap_out_syms (abfd)
              }
            value += sec->vma;
            sym.st_value = value;
-           type_ptr = elf_symbol_from (abfd, syms[idx]);
            sym.st_size = type_ptr ? type_ptr->internal_elf_sym.st_size : 0;
            sym.st_shndx = shndx = elf_section_from_bfd_section (abfd, sec);
            if (shndx == -1)
@@ -2323,7 +2328,7 @@ swap_out_syms (abfd)
 
        if (bfd_is_com_section (syms[idx]->section))
          sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_OBJECT);
-       else if (syms[idx]->section == &bfd_und_section)
+       else if (bfd_is_und_section (syms[idx]->section))
          sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_NOTYPE);
        else if (syms[idx]->flags & BSF_SECTION_SYM)
          sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
@@ -2488,7 +2493,7 @@ NAME(bfd_elf,write_object_contents) (abfd)
     }
 
   if (bed->elf_backend_final_write_processing)
-    (*bed->elf_backend_final_write_processing) (abfd);
+    (*bed->elf_backend_final_write_processing) (abfd, NULL);
 
   return write_shdrs_and_ehdr (abfd);
 }
@@ -2507,13 +2512,13 @@ section_from_elf_index (abfd, index)
      bfd *abfd;
      unsigned int index;
 {
-  /* @@ Is bfd_com_section really correct in all the places it could
+  /* @@ Is bfd_com_section_ptr really correct in all the places it could
      be returned from this routine?  */
 
   if (index == SHN_ABS)
-    return &bfd_com_section;   /* not abs? */
+    return bfd_com_section_ptr;        /* not abs? */
   if (index == SHN_COMMON)
-    return &bfd_com_section;
+    return bfd_com_section_ptr;
 
   if (index > elf_elfheader (abfd)->e_shnum)
     return NULL;
@@ -2536,7 +2541,7 @@ section_from_elf_index (abfd, index)
        return (struct sec *) hdr->rawdata;
 
       default:
-       return (struct sec *) &bfd_abs_section;
+       return bfd_abs_section_ptr;
       }
   }
 }
@@ -2552,12 +2557,18 @@ elf_section_from_bfd_section (abfd, asect)
   Elf_Internal_Shdr *hdr;
   int maxindex = elf_elfheader (abfd)->e_shnum;
 
-  if (asect == &bfd_abs_section)
-    return SHN_ABS;
-  if (asect == &bfd_com_section)
-    return SHN_COMMON;
-  if (asect == &bfd_und_section)
-    return SHN_UNDEF;
+  if (asect->owner == NULL)
+    {
+      if (bfd_is_abs_section (asect))
+       return SHN_ABS;
+      if (bfd_is_com_section (asect))
+       return SHN_COMMON;
+      if (bfd_is_und_section (asect))
+       return SHN_UNDEF;
+      return -1;
+    }
+
+  BFD_ASSERT (asect->owner == abfd);
 
   for (index = 0; index < maxindex; index++)
     {
@@ -2749,16 +2760,16 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
                  /* This symbol is in a section for which we did not
                     create a BFD section.  Just use bfd_abs_section,
                     although it is wrong.  FIXME.  */
-                 sym->symbol.section = &bfd_abs_section;
+                 sym->symbol.section = bfd_abs_section_ptr;
                }
            }
          else if (i_sym.st_shndx == SHN_ABS)
            {
-             sym->symbol.section = &bfd_abs_section;
+             sym->symbol.section = bfd_abs_section_ptr;
            }
          else if (i_sym.st_shndx == SHN_COMMON)
            {
-             sym->symbol.section = &bfd_com_section;
+             sym->symbol.section = bfd_com_section_ptr;
              /* Elf puts the alignment into the `value' field, and
                 the size into the `size' field.  BFD wants to see the
                 size in the value field, and doesn't care (at the
@@ -2767,10 +2778,10 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
            }
          else if (i_sym.st_shndx == SHN_UNDEF)
            {
-             sym->symbol.section = &bfd_und_section;
+             sym->symbol.section = bfd_und_section_ptr;
            }
          else
-           sym->symbol.section = &bfd_abs_section;
+           sym->symbol.section = bfd_abs_section_ptr;
 
          sym->symbol.value -= sym->symbol.section->vma;
 
@@ -2876,131 +2887,140 @@ elf_get_dynamic_symtab_upper_bound (abfd)
   long symtab_size;
   Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->dynsymtab_hdr;
 
+  if (elf_dynsymtab (abfd) == 0)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return -1;
+    }
+
   symcount = hdr->sh_size / sizeof (Elf_External_Sym);
   symtab_size = (symcount - 1 + 1) * (sizeof (asymbol *));
 
   return symtab_size;
 }
 
-/*
-       This function return the number of bytes required to store the
-       relocation information associated with section <<sect>>
-       attached to bfd <<abfd>>
-
-*/
 long
 elf_get_reloc_upper_bound (abfd, asect)
      bfd *abfd;
      sec_ptr asect;
 {
-  if (asect->flags & SEC_RELOC)
-    {
-      /* either rel or rela */
-      return elf_section_data (asect)->rel_hdr.sh_size;
-    }
-  else
-    return 0;
+  return (asect->reloc_count + 1) * sizeof (arelent *);
 }
 
+/* Read in and swap the external relocs.  */
+
 static boolean
-elf_slurp_reloca_table (abfd, asect, symbols)
+elf_slurp_reloc_table (abfd, asect, symbols)
      bfd *abfd;
-     sec_ptr asect;
+     asection *asect;
      asymbol **symbols;
 {
-  Elf_External_Rela *native_relocs;
-  arelent *reloc_cache;
-  arelent *cache_ptr;
-
-  unsigned int idx;
+  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)
-    return true;
-  if (asect->reloc_count == 0)
-    return true;
-  if (asect->flags & SEC_CONSTRUCTOR)
+  if (asect->relocation != NULL)
     return true;
 
-  if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
-    return false;
-  native_relocs = (Elf_External_Rela *)
-    bfd_alloc (abfd, asect->reloc_count * sizeof (Elf_External_Rela));
-  if (!native_relocs)
+  BFD_ASSERT (asect->rel_filepos == d->rel_hdr.sh_offset
+             && (asect->reloc_count
+                 == d->rel_hdr.sh_size / d->rel_hdr.sh_entsize));
+
+  native_relocs = (bfd_byte *) elf_section_data (asect)->relocs;
+  if (native_relocs == NULL)
     {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
-  if (bfd_read ((PTR) native_relocs,
-               sizeof (Elf_External_Rela), asect->reloc_count, abfd)
-      != sizeof (Elf_External_Rela) * asect->reloc_count)
-    return false;
+      allocated = (PTR) malloc (d->rel_hdr.sh_size);
+      if (allocated == NULL)
+       {
+         bfd_set_error (bfd_error_no_memory);
+         goto error_return;
+       }
 
-  reloc_cache = (arelent *)
-    bfd_alloc (abfd, (size_t) (asect->reloc_count * sizeof (arelent)));
+      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))
+       goto error_return;
 
-  if (!reloc_cache)
+      native_relocs = (bfd_byte *) allocated;
+    }
+
+  relents = ((arelent *)
+            bfd_alloc (abfd, asect->reloc_count * sizeof (arelent)));
+  if (relents == NULL)
     {
       bfd_set_error (bfd_error_no_memory);
-      return false;
+      goto error_return;
     }
 
-  for (idx = 0; idx < asect->reloc_count; idx++)
-    {
-      Elf_Internal_Rela dst;
-      Elf_External_Rela *src;
+  entsize = d->rel_hdr.sh_entsize;
+  BFD_ASSERT (entsize == sizeof (Elf_External_Rel)
+             || entsize == sizeof (Elf_External_Rela));
 
-      cache_ptr = reloc_cache + idx;
-      src = native_relocs + idx;
-      elf_swap_reloca_in (abfd, src, &dst);
+  for (i = 0, relent = relents;
+       i < asect->reloc_count;
+       i++, relent++, native_relocs += entsize)
+    {
+      Elf_Internal_Rela rela;
+      Elf_Internal_Rel rel;
 
-#ifdef RELOC_PROCESSING
-      RELOC_PROCESSING (cache_ptr, &dst, symbols, abfd, asect);
-#else
-      if (asect->flags & SEC_RELOC)
-       {
-         /* relocatable, so the offset is off of the section */
-         cache_ptr->address = dst.r_offset + asect->vma;
-       }
+      if (entsize == sizeof (Elf_External_Rela))
+       elf_swap_reloca_in (abfd, (Elf_External_Rela *) native_relocs, &rela);
       else
        {
-         /* non-relocatable, so the offset a virtual address */
-         cache_ptr->address = dst.r_offset;
+         elf_swap_reloc_in (abfd, (Elf_External_Rel *) native_relocs, &rel);
+         rela.r_offset = rel.r_offset;
+         rela.r_info = rel.r_info;
+         rela.r_addend = 0;
        }
 
-      /* ELF_R_SYM(dst.r_info) is the symbol table offset.  An offset
-        of zero points to the dummy symbol, which was not read into
-        the symbol table SYMBOLS.  */
-      if (ELF_R_SYM (dst.r_info) == 0)
-       cache_ptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
+      /* 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)
+       relent->address = rela.r_offset;
+      else
+       relent->address = rela.r_offset - asect->vma;
+
+      if (ELF_R_SYM (rela.r_info) == 0)
+       relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
       else
        {
-         asymbol *s;
+         asymbol **ps, *s;
 
-         cache_ptr->sym_ptr_ptr = symbols + ELF_R_SYM (dst.r_info) - 1;
+         ps = symbols + ELF_R_SYM (rela.r_info) - 1;
+         s = *ps;
 
-         /* Translate any ELF section symbol into a BFD section
-            symbol.  */
-         s = *(cache_ptr->sym_ptr_ptr);
-         if (s->flags & BSF_SECTION_SYM)
-           {
-             cache_ptr->sym_ptr_ptr = s->section->symbol_ptr_ptr;
-             s = *cache_ptr->sym_ptr_ptr;
-             if (s->name == 0 || s->name[0] == 0)
-               abort ();
-           }
+         /* Canonicalize ELF section symbols.  FIXME: Why?  */
+         if ((s->flags & BSF_SECTION_SYM) == 0)
+           relent->sym_ptr_ptr = ps;
+         else
+           relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
        }
-      cache_ptr->addend = dst.r_addend;
 
-      /* Fill in the cache_ptr->howto field from dst.r_type */
-      {
-       struct elf_backend_data *ebd = get_elf_backend_data (abfd);
-       (*ebd->elf_info_to_howto) (abfd, cache_ptr, &dst);
-      }
-#endif
+      relent->addend = rela.r_addend;
+
+      if (entsize == sizeof (Elf_External_Rela))
+       (*ebd->elf_info_to_howto) (abfd, relent, &rela);
+      else
+       (*ebd->elf_info_to_howto_rel) (abfd, relent, &rel);
     }
 
-  asect->relocation = reloc_cache;
+  asect->relocation = relents;
+
+  if (allocated != NULL)
+    free (allocated);
+
   return true;
+
+ error_return:
+  if (allocated != NULL)
+    free (allocated);
+  return false;
 }
 
 #ifdef DEBUG
@@ -3048,129 +3068,7 @@ elf_debug_file (ehdrp)
 }
 #endif
 
-static boolean
-elf_slurp_reloc_table (abfd, asect, symbols)
-     bfd *abfd;
-     sec_ptr asect;
-     asymbol **symbols;
-{
-  Elf_External_Rel *native_relocs;
-  arelent *reloc_cache;
-  arelent *cache_ptr;
-  Elf_Internal_Shdr *data_hdr;
-  bfd_vma data_off;
-  unsigned long data_max;
-  char buf[4];                 /* FIXME -- might be elf64 */
-
-  unsigned int idx;
-
-  if (asect->relocation)
-    return true;
-  if (asect->reloc_count == 0)
-    return true;
-  if (asect->flags & SEC_CONSTRUCTOR)
-    return true;
-
-  if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
-    return false;
-  native_relocs = (Elf_External_Rel *)
-    bfd_alloc (abfd, asect->reloc_count * sizeof (Elf_External_Rel));
-  if (!native_relocs)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
-  if (bfd_read ((PTR) native_relocs,
-               sizeof (Elf_External_Rel), asect->reloc_count, abfd)
-      != sizeof (Elf_External_Rel) * asect->reloc_count)
-    return false;
-
-  reloc_cache = (arelent *)
-    bfd_alloc (abfd, (size_t) (asect->reloc_count * sizeof (arelent)));
-
-  if (!reloc_cache)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
-
-  /* Get the offset of the start of the segment we are relocating to read in
-     the implicit addend.  */
-  data_hdr = &elf_section_data (asect)->this_hdr;
-  data_off = data_hdr->sh_offset;
-  data_max = data_hdr->sh_size - sizeof (buf) + 1;
-
-#if DEBUG & 2
-  elf_debug_section ("data section", -1, data_hdr);
-#endif
-
-  for (idx = 0; idx < asect->reloc_count; idx++)
-    {
-#ifdef RELOC_PROCESSING
-      Elf_Internal_Rel dst;
-      Elf_External_Rel *src;
-
-      cache_ptr = reloc_cache + idx;
-      src = native_relocs + idx;
-      elf_swap_reloc_in (abfd, src, &dst);
-
-      RELOC_PROCESSING (cache_ptr, &dst, symbols, abfd, asect);
-#else
-      Elf_Internal_Rel dst;
-      Elf_External_Rel *src;
-
-      cache_ptr = reloc_cache + idx;
-      src = native_relocs + idx;
-
-      elf_swap_reloc_in (abfd, src, &dst);
-
-      if (asect->flags & SEC_RELOC)
-       {
-         /* relocatable, so the offset is off of the section */
-         cache_ptr->address = dst.r_offset + asect->vma;
-       }
-      else
-       {
-         /* non-relocatable, so the offset a virtual address */
-         cache_ptr->address = dst.r_offset;
-       }
-
-      /* ELF_R_SYM(dst.r_info) is the symbol table offset.  An offset
-        of zero points to the dummy symbol, which was not read into
-        the symbol table SYMBOLS.  */
-      if (ELF_R_SYM (dst.r_info) == 0)
-       cache_ptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
-      else
-       {
-         asymbol *s;
-
-         cache_ptr->sym_ptr_ptr = symbols + ELF_R_SYM (dst.r_info) - 1;
-
-         /* Translate any ELF section symbol into a BFD section
-            symbol.  */
-         s = *(cache_ptr->sym_ptr_ptr);
-         if (s->flags & BSF_SECTION_SYM)
-           {
-             cache_ptr->sym_ptr_ptr = s->section->symbol_ptr_ptr;
-             s = *cache_ptr->sym_ptr_ptr;
-             if (s->name == 0 || s->name[0] == 0)
-               abort ();
-           }
-       }
-      BFD_ASSERT (dst.r_offset <= data_max);
-      cache_ptr->addend = 0;
-
-      /* Fill in the cache_ptr->howto field from dst.r_type */
-      {
-       struct elf_backend_data *ebd = get_elf_backend_data (abfd);
-       (*ebd->elf_info_to_howto_rel) (abfd, cache_ptr, &dst);
-      }
-#endif
-    }
-
-  asect->relocation = reloc_cache;
-  return true;
-}
+/* Canonicalize the relocs.  */
 
 long
 elf_canonicalize_reloc (abfd, section, relptr, symbols)
@@ -3179,28 +3077,18 @@ elf_canonicalize_reloc (abfd, section, relptr, symbols)
      arelent **relptr;
      asymbol **symbols;
 {
-  arelent *tblptr = section->relocation;
-  unsigned int count = 0;
-  int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
+  arelent *tblptr;
+  unsigned int i;
 
-  /* snarfed from coffcode.h */
-  if (use_rela_p)
-    {
-      if (! elf_slurp_reloca_table (abfd, section, symbols))
-       return -1;
-    }
-  else
-    {
-      if (! elf_slurp_reloc_table (abfd, section, symbols))
-       return -1;
-    }
+  if (! elf_slurp_reloc_table (abfd, section, symbols))
+    return -1;
 
   tblptr = section->relocation;
-
-  for (; count++ < section->reloc_count;)
+  for (i = 0; i < section->reloc_count; i++)
     *relptr++ = tblptr++;
 
-  *relptr = 0;
+  *relptr = NULL;
+
   return section->reloc_count;
 }
 
@@ -3420,7 +3308,7 @@ bfd_prstatus (abfd, descdata, descsz, filepos)
        return false;
       newsect->_raw_size = sizeof (status->pr_reg);
       newsect->filepos = filepos + (long) &status->pr_reg;
-      newsect->flags = SEC_ALLOC | SEC_HAS_CONTENTS;
+      newsect->flags = SEC_HAS_CONTENTS;
       newsect->alignment_power = 2;
       if ((core_prstatus (abfd) = bfd_alloc (abfd, descsz)) != NULL)
        {
@@ -3465,7 +3353,7 @@ bfd_fpregset (abfd, descdata, descsz, filepos)
     return false;
   newsect->_raw_size = descsz;
   newsect->filepos = filepos;
-  newsect->flags = SEC_ALLOC | SEC_HAS_CONTENTS;
+  newsect->flags = SEC_HAS_CONTENTS;
   newsect->alignment_power = 2;
   return true;
 }
@@ -4142,7 +4030,23 @@ elf_link_add_object_symbols (abfd, info)
   elf_sym_hashes (abfd) = sym_hash;
 
   if (elf_elfheader (abfd)->e_type != ET_DYN)
-    dynamic = false;
+    {
+      dynamic = false;
+
+      /* If we are creating a shared library, create all the dynamic
+         sections immediately.  We need to attach them to something,
+         so we attach them to this BFD, provided it is the right
+         format.  FIXME: If there are no input BFD's of the same
+         format as the output, we can't make a shared library.  */
+      if (info->shared
+         && elf_hash_table (info)->dynobj == NULL
+         && abfd->xvec == info->hash->creator)
+       {
+         if (! elf_link_create_dynamic_sections (abfd, info))
+           goto error_return;
+         elf_hash_table (info)->dynobj = abfd;
+       }
+    }
   else
     {
       asection *s;
@@ -4293,7 +4197,7 @@ elf_link_add_object_symbols (abfd, info)
        }
 
       if (sym.st_shndx == SHN_UNDEF)
-       sec = &bfd_und_section;
+       sec = bfd_und_section_ptr;
       else if (sym.st_shndx > 0 && sym.st_shndx < SHN_LORESERVE)
        {
          sec = section_from_elf_index (abfd, sym.st_shndx);
@@ -4302,10 +4206,10 @@ elf_link_add_object_symbols (abfd, info)
          value -= sec->vma;
        }
       else if (sym.st_shndx == SHN_ABS)
-       sec = &bfd_abs_section;
+       sec = bfd_abs_section_ptr;
       else if (sym.st_shndx == SHN_COMMON)
        {
-         sec = &bfd_com_section;
+         sec = bfd_com_section_ptr;
          /* What ELF calls the size we call the value.  What ELF
             calls the value we call the alignment.  */
          value = sym.st_size;
@@ -4338,7 +4242,7 @@ elf_link_add_object_symbols (abfd, info)
          goto error_return;
        }
 
-      if (sec == &bfd_und_section
+      if (bfd_is_und_section (sec)
          || bfd_is_com_section (sec))
        definition = false;
       else
@@ -4361,11 +4265,11 @@ elf_link_add_object_symbols (abfd, info)
             by some other object.  If it has, we want to use the
             existing definition, and we do not want to report a
             multiple symbol definition error; we do this by
-            clobbering sec to be bfd_und_section.  */
+            clobbering sec to be bfd_und_section_ptr.  */
          if (dynamic && definition)
            {
              if (h->root.type == bfd_link_hash_defined)
-               sec = &bfd_und_section;
+               sec = bfd_und_section_ptr;
            }
 
          /* Similarly, if we are not looking at a dynamic object, and
@@ -4388,7 +4292,19 @@ elf_link_add_object_symbols (abfd, info)
                 with the new definition.  */
              h->root.type = bfd_link_hash_undefined;
              h->root.u.undef.abfd = h->root.u.def.section->owner;
+             h->elf_link_hash_flags &=~ ELF_LINK_HASH_DEFINED_WEAK;
            }
+
+         /* If this is a weak definition which we are going to use,
+            and the symbol is currently undefined, record that the
+            definition is weak.  */
+         if (definition
+             && (flags & BSF_WEAK) != 0
+             && ! bfd_is_und_section (sec)
+             && (h->root.type == bfd_link_hash_new
+                 || h->root.type == bfd_link_hash_undefined
+                 || h->root.type == bfd_link_hash_weak))
+           h->elf_link_hash_flags |= ELF_LINK_HASH_DEFINED_WEAK;
        }
 
       if (! (_bfd_generic_link_add_one_symbol
@@ -4582,10 +4498,15 @@ elf_link_create_dynamic_sections (abfd, info)
      sections.  */
   flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
 
-  s = bfd_make_section (abfd, ".interp");
-  if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY))
-    return false;
+  /* A dynamically linked executable has a .interp section, but a
+     shared library does not.  */
+  if (! info->shared)
+    {
+      s = bfd_make_section (abfd, ".interp");
+      if (s == NULL
+         || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY))
+       return false;
+    }
 
   s = bfd_make_section (abfd, ".dynamic");
   if (s == NULL
@@ -4742,8 +4663,9 @@ static const size_t elf_buckets[] =
    addresses of the various sections.  */
 
 boolean
-NAME(bfd_elf,size_dynamic_sections) (output_bfd, info, sinterpptr)
+NAME(bfd_elf,size_dynamic_sections) (output_bfd, rpath, info, sinterpptr)
      bfd *output_bfd;
+     const char *rpath;
      struct bfd_link_info *info;
      asection **sinterpptr;
 {
@@ -4766,7 +4688,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, info, sinterpptr)
     return true;
 
   *sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
-  BFD_ASSERT (*sinterpptr != NULL);
+  BFD_ASSERT (*sinterpptr != NULL || info->shared);
 
   /* Set the size of the .dynsym and .hash sections.  We counted the
      number of dynamic symbols in elf_link_add_object_symbols.  We
@@ -4817,6 +4739,16 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, info, sinterpptr)
 
   elf_hash_table (info)->bucketcount = bucketcount;
 
+  if (rpath != NULL)
+    {
+      unsigned long indx;
+
+      indx = bfd_add_to_strtab (dynobj, elf_hash_table (info)->dynstr, rpath);
+      if (indx == (unsigned long) -1
+         || ! elf_add_dynamic_entry (info, DT_RPATH, indx))
+       return false;
+    }
+
   s = bfd_get_section_by_name (dynobj, ".dynstr");
   BFD_ASSERT (s != NULL);
   s->_raw_size = elf_hash_table (info)->dynstr->length;
@@ -5000,7 +4932,8 @@ struct elf_final_link_info
 };
 
 static boolean elf_link_output_sym
-  PARAMS ((struct elf_final_link_info *, const char *, Elf_Internal_Sym *));
+  PARAMS ((struct elf_final_link_info *, const char *,
+          Elf_Internal_Sym *, asection *));
 static boolean elf_link_flush_output_syms
   PARAMS ((struct elf_final_link_info *));
 static boolean elf_link_output_extsym
@@ -5032,6 +4965,7 @@ elf_bfd_final_link (abfd, info)
   unsigned int i;
   Elf_Internal_Shdr *symtab_hdr;
   Elf_Internal_Shdr *symstrtab_hdr;
+  struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   if (info->shared)
     {
@@ -5238,7 +5172,8 @@ elf_bfd_final_link (abfd, info)
   elfsym.st_info = 0;
   elfsym.st_other = 0;
   elfsym.st_shndx = SHN_UNDEF;
-  if (! elf_link_output_sym (&finfo, (const char *) NULL, &elfsym))
+  if (! elf_link_output_sym (&finfo, (const char *) NULL,
+                            &elfsym, bfd_und_section_ptr))
     goto error_return;
 
 #if 0
@@ -5252,7 +5187,8 @@ elf_bfd_final_link (abfd, info)
   elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
   elfsym.st_other = 0;
   elfsym.st_shndx = SHN_ABS;
-  if (! elf_link_output_sym (&finfo, bfd_get_filename (abfd), &elfsym))
+  if (! elf_link_output_sym (&finfo, bfd_get_filename (abfd),
+                            &elfsym, bfd_abs_section_ptr))
     goto error_return;
 #endif
 
@@ -5268,10 +5204,11 @@ elf_bfd_final_link (abfd, info)
   for (i = 1; i < elf_elfheader (abfd)->e_shnum; i++)
     {
       o = section_from_elf_index (abfd, i);
-      if (o != &bfd_abs_section)
+      if (! bfd_is_abs_section (o))
        o->target_index = abfd->symcount;
       elfsym.st_shndx = i;
-      if (! elf_link_output_sym (&finfo, (const char *) NULL, &elfsym))
+      if (! elf_link_output_sym (&finfo, (const char *) NULL,
+                                &elfsym, o))
        goto error_return;
     }
 
@@ -5444,7 +5381,6 @@ elf_bfd_final_link (abfd, info)
   if (dynobj != NULL)
     {
       Elf_External_Dyn *dyncon, *dynconend;
-      struct elf_backend_data *bed;
 
       /* Fix up .dynamic entries.  */
       o = bfd_get_section_by_name (dynobj, ".dynamic");
@@ -5518,7 +5454,6 @@ elf_bfd_final_link (abfd, info)
            }
        }
 
-      bed = get_elf_backend_data (abfd);
       if (! (*bed->elf_backend_finish_dynamic_sections) (abfd, info))
        goto error_return;
 
@@ -5526,7 +5461,11 @@ elf_bfd_final_link (abfd, info)
        {
          if ((o->flags & SEC_HAS_CONTENTS) == 0)
            continue;
-         BFD_ASSERT ((o->flags & SEC_IN_MEMORY) != 0);
+         if ((o->flags & SEC_IN_MEMORY) == 0)
+           {
+             BFD_ASSERT (info->shared);
+             continue;
+           }
          if (! bfd_set_section_contents (abfd, o->output_section,
                                          o->contents, o->output_offset,
                                          o->_raw_size))
@@ -5534,6 +5473,10 @@ elf_bfd_final_link (abfd, info)
        }
     }
 
+  /* Now backend stuff.  */
+  if (bed->elf_backend_final_write_processing)
+    (*bed->elf_backend_final_write_processing) (abfd, NULL);
+
   if (finfo.contents != NULL)
     free (finfo.contents);
   if (finfo.external_relocs != NULL)
@@ -5589,11 +5532,27 @@ elf_bfd_final_link (abfd, info)
 /* Add a symbol to the output symbol table.  */
 
 static boolean
-elf_link_output_sym (finfo, name, elfsym)
+elf_link_output_sym (finfo, name, elfsym, input_sec)
      struct elf_final_link_info *finfo;
      const char *name;
      Elf_Internal_Sym *elfsym;
+     asection *input_sec;
 {
+  boolean (*output_symbol_hook) PARAMS ((bfd *,
+                                        struct bfd_link_info *info,
+                                        const char *,
+                                        Elf_Internal_Sym *,
+                                        asection *));
+
+  output_symbol_hook = get_elf_backend_data (finfo->output_bfd)->
+    elf_backend_link_output_symbol_hook;
+  if (output_symbol_hook != NULL)
+    {
+      if (! ((*output_symbol_hook)
+            (finfo->output_bfd, finfo->info, name, elfsym, input_sec)))
+       return false;
+    }
+
   if (name == (const char *) NULL || *name == '\0')
     elfsym->st_name = 0;
   else
@@ -5654,6 +5613,7 @@ elf_link_output_extsym (h, data)
   struct elf_final_link_info *finfo = (struct elf_final_link_info *) data;
   boolean strip;
   Elf_Internal_Sym sym;
+  asection *input_sec;
 
   /* We don't want to output symbols that have never been mentioned by
      a regular file, or that we have been told to strip.  However, if
@@ -5682,8 +5642,12 @@ elf_link_output_extsym (h, data)
 
   sym.st_value = 0;
   sym.st_size = h->size;
-  sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
   sym.st_other = 0;
+  if (h->root.type == bfd_link_hash_weak
+      || (h->elf_link_hash_flags & ELF_LINK_HASH_DEFINED_WEAK) != 0)
+    sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
+  else
+    sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
 
   switch (h->root.type)
     {
@@ -5693,23 +5657,23 @@ elf_link_output_extsym (h, data)
       return false;
 
     case bfd_link_hash_undefined:
+      input_sec = bfd_und_section_ptr;
       sym.st_shndx = SHN_UNDEF;
       break;
 
     case bfd_link_hash_weak:
+      input_sec = bfd_und_section_ptr;
       sym.st_shndx = SHN_UNDEF;
-      sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
       break;
 
     case bfd_link_hash_defined:
       {
-       asection *sec;
 
-       sec = h->root.u.def.section;
-       if (sec->output_section != NULL)
+       input_sec = h->root.u.def.section;
+       if (input_sec->output_section != NULL)
          {
            sym.st_shndx = elf_section_from_bfd_section (finfo->output_bfd,
-                                                        sec->output_section);
+                                                        input_sec->output_section);
            if (sym.st_shndx == (unsigned short) -1)
              {
                /* FIXME: No way to handle errors.  */
@@ -5719,20 +5683,23 @@ elf_link_output_extsym (h, data)
            /* ELF symbols in relocateable files are section relative,
               but in nonrelocateable files they are virtual
               addresses.  */
-           sym.st_value = h->root.u.def.value + sec->output_offset;
+           sym.st_value = h->root.u.def.value + input_sec->output_offset;
            if (! finfo->info->relocateable)
-             sym.st_value += sec->output_section->vma;
+             sym.st_value += input_sec->output_section->vma;
          }
        else
          {
-           BFD_ASSERT (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour
-                       && elf_elfheader (sec->owner)->e_type == ET_DYN);
+           BFD_ASSERT (bfd_get_flavour (input_sec->owner)
+                       == bfd_target_elf_flavour
+                       && elf_elfheader (input_sec->owner)->e_type == ET_DYN);
            sym.st_shndx = SHN_UNDEF;
+           input_sec = bfd_und_section_ptr;
          }
       }
       break;
 
     case bfd_link_hash_common:
+      input_sec = bfd_com_section_ptr;
       sym.st_shndx = SHN_COMMON;
       if (h->align == 0)
        sym.st_value = 1;
@@ -5792,7 +5759,7 @@ elf_link_output_extsym (h, data)
 
   h->indx = finfo->output_bfd->symcount;
 
-  if (! elf_link_output_sym (finfo, h->root.root.string, &sym))
+  if (! elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec))
     {
       /* FIXME: No way to return error.  */
       abort ();
@@ -5815,7 +5782,7 @@ elf_link_input_bfd (finfo, input_bfd)
                                       bfd *, asection *, bfd_byte *,
                                       Elf_Internal_Rela *,
                                       Elf_Internal_Sym *,
-                                      asection **));
+                                      asection **, char *));
   bfd *output_bfd;
   Elf_Internal_Shdr *symtab_hdr;
   size_t locsymcount;
@@ -5883,7 +5850,7 @@ elf_link_input_bfd (finfo, input_bfd)
        }
 
       if (isym->st_shndx == SHN_UNDEF)
-       isec = &bfd_und_section;
+       isec = bfd_und_section_ptr;
       else if (isym->st_shndx > 0 && isym->st_shndx < SHN_LORESERVE)
        {
          isec = section_from_elf_index (input_bfd, isym->st_shndx);
@@ -5891,9 +5858,9 @@ elf_link_input_bfd (finfo, input_bfd)
            return false;
        }
       else if (isym->st_shndx == SHN_ABS)
-       isec = &bfd_abs_section;
+       isec = bfd_abs_section_ptr;
       else if (isym->st_shndx == SHN_COMMON)
-       isec = &bfd_com_section;
+       isec = bfd_com_section_ptr;
       else
        {
          /* Who knows?  */
@@ -5961,7 +5928,7 @@ elf_link_input_bfd (finfo, input_bfd)
       if (! finfo->info->relocateable)
        isym->st_value += isec->output_section->vma;
 
-      if (! elf_link_output_sym (finfo, name, isym))
+      if (! elf_link_output_sym (finfo, name, isym, isec))
        return false;
 
       /* Restore the old value for reloc handling.  */
@@ -5976,6 +5943,14 @@ elf_link_input_bfd (finfo, input_bfd)
       if ((o->flags & SEC_HAS_CONTENTS) == 0)
        continue;
 
+      if ((o->flags & SEC_IN_MEMORY) != 0
+         && input_bfd == elf_hash_table (finfo->info)->dynobj)
+       {
+         /* Section was created by elf_link_create_dynamic_sections.
+             FIXME: This test is fragile.  */
+         continue;
+       }
+
       /* Read the contents of the section.  */
       if (! bfd_get_section_contents (input_bfd, o, finfo->contents,
                                      (file_ptr) 0, o->_raw_size))
@@ -5983,12 +5958,21 @@ elf_link_input_bfd (finfo, input_bfd)
 
       if ((o->flags & SEC_RELOC) != 0)
        {
-         /* Read in the relocs.  */
-         input_rel_hdr = &elf_section_data (o)->rel_hdr;
-         if (bfd_seek (input_bfd, input_rel_hdr->sh_offset, SEEK_SET) != 0
-             || bfd_read (finfo->external_relocs, 1, input_rel_hdr->sh_size,
-                          input_bfd) != input_rel_hdr->sh_size)
-           return false;
+         PTR external_relocs;
+
+         /* Get the external relocs.  They may have been cached.  */
+         external_relocs = elf_section_data (o)->relocs;
+         if (external_relocs == NULL)
+           {
+             input_rel_hdr = &elf_section_data (o)->rel_hdr;
+             if ((bfd_seek (input_bfd, input_rel_hdr->sh_offset, SEEK_SET)
+                  != 0)
+                 || (bfd_read (finfo->external_relocs, 1,
+                              input_rel_hdr->sh_size, input_bfd)
+                     != input_rel_hdr->sh_size))
+               return false;
+             external_relocs = finfo->external_relocs;
+           }
 
          /* Swap in the relocs.  For convenience, we always produce
             an Elf_Internal_Rela array; if the relocs are Rel, we set
@@ -5999,7 +5983,7 @@ elf_link_input_bfd (finfo, input_bfd)
              Elf_External_Rel *erelend;
              Elf_Internal_Rela *irela;
 
-             erel = (Elf_External_Rel *) finfo->external_relocs;
+             erel = (Elf_External_Rel *) external_relocs;
              erelend = erel + o->reloc_count;
              irela = finfo->internal_relocs;
              for (; erel < erelend; erel++, irela++)
@@ -6021,7 +6005,7 @@ elf_link_input_bfd (finfo, input_bfd)
              BFD_ASSERT (input_rel_hdr->sh_entsize
                          == sizeof (Elf_External_Rela));
 
-             erela = (Elf_External_Rela *) finfo->external_relocs;
+             erela = (Elf_External_Rela *) external_relocs;
              erelaend = erela + o->reloc_count;
              irela = finfo->internal_relocs;
              for (; erela < erelaend; erela++, irela++)
@@ -6053,7 +6037,8 @@ elf_link_input_bfd (finfo, input_bfd)
                                     finfo->contents,
                                     finfo->internal_relocs,
                                     finfo->internal_syms,
-                                    finfo->sections))
+                                    finfo->sections,
+                                    finfo->symstrtab->tab))
            return false;
 
          if (finfo->info->relocateable)
@@ -6117,15 +6102,13 @@ elf_link_input_bfd (finfo, input_bfd)
                      /* I suppose the backend ought to fill in the
                         section of any STT_SECTION symbol against a
                         processor specific section.  */
-                     if (sec == NULL
-                         || sec == &bfd_und_section
-                         || sec == &bfd_com_section)
+                     if (sec != NULL && bfd_is_abs_section (sec))
+                       r_symndx = 0;
+                     else if (sec == NULL || sec->owner == NULL)
                        {
                          bfd_set_error (bfd_error_bad_value);
                          return false;
                        }
-                     else if (sec == &bfd_abs_section)
-                       r_symndx = 0;
                      else
                        {
                          r_symndx = sec->output_section->target_index;
@@ -6171,7 +6154,7 @@ elf_link_input_bfd (finfo, input_bfd)
 
                          finfo->indices[r_symndx] = output_bfd->symcount;
 
-                         if (! elf_link_output_sym (finfo, name, isym))
+                         if (! elf_link_output_sym (finfo, name, isym, sec))
                            return false;
                        }
 
This page took 0.036826 seconds and 4 git commands to generate.