2000-07-19 H.J. Lu <hjl@gnu.org>
[deliverable/binutils-gdb.git] / bfd / elflink.h
index 5d86bbc5338ee457aa81d6f5519cdaa078b72133..7fa35a936ce0eee2f13a93babdf84117ddbe89bc 100644 (file)
@@ -890,7 +890,7 @@ elf_link_add_object_symbols (abfd, info)
   Elf_External_Sym *esym;
   Elf_External_Sym *esymend;
   struct elf_backend_data *bed;
-  boolean visibility_changed = false;
+  boolean dt_needed;
 
   bed = get_elf_backend_data (abfd);
   add_symbol_hook = bed->elf_add_symbol_hook;
@@ -1050,6 +1050,8 @@ elf_link_add_object_symbols (abfd, info)
     goto error_return;
   elf_sym_hashes (abfd) = sym_hash;
 
+  dt_needed = false;
+
   if (! dynamic)
     {
       /* If we are creating a shared library, create all the dynamic
@@ -1086,7 +1088,12 @@ elf_link_add_object_symbols (abfd, info)
        {
          name = elf_dt_name (abfd);
          if (*name == '\0')
-           add_needed = false;
+           {
+             if (elf_dt_soname (abfd) != NULL)
+               dt_needed = true;
+
+             add_needed = false;
+           }
        }
       s = bfd_get_section_by_name (abfd, ".dynamic");
       if (s != NULL)
@@ -1581,10 +1588,7 @@ elf_link_add_object_symbols (abfd, info)
              unsigned char symvis = ELF_ST_VISIBILITY (sym.st_other);
              
              if (symvis && (hvis > symvis || hvis == 0))
-               {
-                 visibility_changed = true;
-                 h->other = sym.st_other;
-               }
+               h->other = sym.st_other;
              
              /* If neither has visibility, use the st_other of the
                 definition.  This is an arbitrary choice, since the
@@ -1855,7 +1859,7 @@ elf_link_add_object_symbols (abfd, info)
                    goto error_return;
                }
            }
-         else if (dynsym && h->dynindx != -1 && visibility_changed)
+         else if (dynsym && h->dynindx != -1)
            /* If the symbol already has a dynamic index, but
               visibility says it should not be visible, turn it into
               a local symbol.  */
@@ -1864,9 +1868,56 @@ elf_link_add_object_symbols (abfd, info)
              case STV_INTERNAL:
              case STV_HIDDEN:  
                h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
-               (*bed->elf_backend_hide_symbol) (h);
+               (*bed->elf_backend_hide_symbol) (info, h);
                break;
              }
+
+         if (dt_needed && definition
+             && (h->elf_link_hash_flags
+                 & ELF_LINK_HASH_REF_REGULAR) != 0)
+           {
+             bfd_size_type oldsize;
+             bfd_size_type strindex;
+
+             /* The symbol from a DT_NEEDED object is referenced from
+                the regular object to create a dynamic executable. We
+                have to make sure there is a DT_NEEDED entry for it. */
+
+             dt_needed = false;
+             oldsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
+             strindex = _bfd_stringtab_add (elf_hash_table (info)->dynstr,
+                                            elf_dt_soname (abfd),
+                                            true, false);
+             if (strindex == (bfd_size_type) -1)
+               goto error_return;
+
+             if (oldsize
+                 == _bfd_stringtab_size (elf_hash_table (info)->dynstr))
+               {
+                 asection *sdyn;
+                 Elf_External_Dyn *dyncon, *dynconend;
+
+                 sdyn = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
+                                                 ".dynamic");
+                 BFD_ASSERT (sdyn != NULL);
+
+                 dyncon = (Elf_External_Dyn *) sdyn->contents;
+                 dynconend = (Elf_External_Dyn *) (sdyn->contents +
+                                                   sdyn->_raw_size);
+                 for (; dyncon < dynconend; dyncon++)
+                   {
+                     Elf_Internal_Dyn dyn;
+
+                     elf_swap_dyn_in (elf_hash_table (info)->dynobj,
+                                      dyncon, &dyn);
+                     BFD_ASSERT (dyn.d_tag != DT_NEEDED ||
+                                 dyn.d_un.d_val != strindex);
+                   }
+               }
+
+             if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
+               goto error_return;
+           }
        }
     }
 
@@ -3293,6 +3344,9 @@ elf_fix_symbol_flags (h, eif)
      an ELF dynamic object.  */
   if ((h->elf_link_hash_flags & ELF_LINK_NON_ELF) != 0)
     {
+      while (h->root.type == bfd_link_hash_indirect)
+       h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
       if (h->root.type != bfd_link_hash_defined
          && h->root.type != bfd_link_hash_defweak)
        h->elf_link_hash_flags |= (ELF_LINK_HASH_REF_REGULAR
@@ -3708,7 +3762,7 @@ elf_link_assign_sym_version (h, data)
                              && ! sinfo->export_dynamic)
                            {
                              h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
-                             (*bed->elf_backend_hide_symbol) (h);
+                             (*bed->elf_backend_hide_symbol) (info, h);
                              /* FIXME: The name of the symbol has
                                 already been recorded in the dynamic
                                 string table section.  */
@@ -3820,7 +3874,7 @@ elf_link_assign_sym_version (h, data)
                          && ! sinfo->export_dynamic)
                        {
                          h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
-                         (*bed->elf_backend_hide_symbol) (h);
+                         (*bed->elf_backend_hide_symbol) (info, h);
                          /* FIXME: The name of the symbol has already
                             been recorded in the dynamic string table
                             section.  */
@@ -3842,7 +3896,7 @@ elf_link_assign_sym_version (h, data)
              && ! sinfo->export_dynamic)
            {
              h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
-             (*bed->elf_backend_hide_symbol) (h);
+             (*bed->elf_backend_hide_symbol) (info, h);
              /* FIXME: The name of the symbol has already been
                 recorded in the dynamic string table section.  */
            }
@@ -3977,6 +4031,7 @@ elf_link_adjust_relocs (abfd, rel_hdr, count, rel_hash)
      struct elf_link_hash_entry **rel_hash;
 {
   unsigned int i;
+  struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   for (i = 0; i < count; i++, rel_hash++)
     {
@@ -3991,10 +4046,16 @@ elf_link_adjust_relocs (abfd, rel_hdr, count, rel_hash)
          Elf_Internal_Rel irel;
          
          erel = (Elf_External_Rel *) rel_hdr->contents + i;
-         elf_swap_reloc_in (abfd, erel, &irel);
+         if (bed->s->swap_reloc_in)
+           (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel, &irel);
+         else
+           elf_swap_reloc_in (abfd, erel, &irel);
          irel.r_info = ELF_R_INFO ((*rel_hash)->indx,
                                    ELF_R_TYPE (irel.r_info));
-         elf_swap_reloc_out (abfd, &irel, erel);
+         if (bed->s->swap_reloc_out)
+           (*bed->s->swap_reloc_out) (abfd, &irel, (bfd_byte *) erel);
+         else
+           elf_swap_reloc_out (abfd, &irel, erel);
        }
       else
        {
@@ -4005,10 +4066,16 @@ elf_link_adjust_relocs (abfd, rel_hdr, count, rel_hash)
                      == sizeof (Elf_External_Rela));
          
          erela = (Elf_External_Rela *) rel_hdr->contents + i;
-         elf_swap_reloca_in (abfd, erela, &irela);
+         if (bed->s->swap_reloca_in)
+           (*bed->s->swap_reloca_in) (abfd, (bfd_byte *) erela, &irela);
+         else
+           elf_swap_reloca_in (abfd, erela, &irela);
          irela.r_info = ELF_R_INFO ((*rel_hash)->indx,
                                     ELF_R_TYPE (irela.r_info));
-         elf_swap_reloca_out (abfd, &irela, erela);
+         if (bed->s->swap_reloca_out)
+           (*bed->s->swap_reloca_out) (abfd, &irela, (bfd_byte *) erela);
+         else
+           elf_swap_reloca_out (abfd, &irela, erela);
        }
     }
 }
@@ -5034,12 +5101,9 @@ elf_link_output_extsym (h, data)
          symbol foo@@GNU_1.2 is the default, which should be used when
          foo is used with no version, then we add an indirect symbol
          foo which points to foo@@GNU_1.2.  We ignore these symbols,
-         since the indirected symbol is already in the hash table.  If
-         the indirect symbol is non-ELF, fall through and output it.  */
-      if ((h->elf_link_hash_flags & ELF_LINK_NON_ELF) == 0)
-       return true;
+         since the indirected symbol is already in the hash table.  */
+      return true;
 
-      /* Fall through.  */
     case bfd_link_hash_warning:
       /* We can't represent these symbols in ELF, although a warning
          symbol may have come from a .gnu.warning.SYMBOL section.  We
@@ -5089,6 +5153,11 @@ elf_link_output_extsym (h, data)
       sym.st_info = ELF_ST_INFO (bindtype, ELF_ST_TYPE (sym.st_info));
     }
 
+  /* If a symbol is not defined locally, we clear the visibility
+     field. */
+  if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+    sym.st_other ^= ELF_ST_VISIBILITY(sym.st_other);
+
   /* If this symbol should be put in the .dynsym section, then put it
      there now.  We have already know the symbol index.  We also fill
      in the entry in the .hash section.  */
@@ -5182,6 +5251,7 @@ elf_link_output_relocs (output_bfd, input_section, input_rel_hdr,
   Elf_Internal_Shdr *output_rel_hdr;
   asection *output_section;
   unsigned int *rel_countp = NULL;
+  struct elf_backend_data *bed;
 
   output_section = input_section->output_section;
   output_rel_hdr = NULL;
@@ -5201,7 +5271,8 @@ elf_link_output_relocs (output_bfd, input_section, input_rel_hdr,
     }
 
   BFD_ASSERT (output_rel_hdr != NULL);
-  
+
+  bed = get_elf_backend_data (output_bfd);
   irela = internal_relocs;
   irelaend = irela + input_rel_hdr->sh_size / input_rel_hdr->sh_entsize;
   if (input_rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
@@ -5216,7 +5287,10 @@ elf_link_output_relocs (output_bfd, input_section, input_rel_hdr,
          irel.r_offset = irela->r_offset;
          irel.r_info = irela->r_info;
          BFD_ASSERT (irela->r_addend == 0);
-         elf_swap_reloc_out (output_bfd, &irel, erel);
+         if (bed->s->swap_reloc_out)
+           (*bed->s->swap_reloc_out) (output_bfd, &irel, (PTR) erel);
+         else
+           elf_swap_reloc_out (output_bfd, &irel, erel);
        }
     }
   else
@@ -5227,7 +5301,10 @@ elf_link_output_relocs (output_bfd, input_section, input_rel_hdr,
                  == sizeof (Elf_External_Rela));
       erela = ((Elf_External_Rela *) output_rel_hdr->contents + *rel_countp);
       for (; irela < irelaend; irela++, erela++)
-       elf_swap_reloca_out (output_bfd, irela, erela);
+       if (bed->s->swap_reloca_out)
+         (*bed->s->swap_reloca_out) (output_bfd, irela, (PTR) erela);
+       else
+         elf_swap_reloca_out (output_bfd, irela, erela);
     }
 
   /* Bump the counter, so that we know where to add the next set of
@@ -5687,6 +5764,7 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
   bfd_vma addend;
   struct elf_link_hash_entry **rel_hash_ptr;
   Elf_Internal_Shdr *rel_hdr;
+  struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
 
   howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
   if (howto == NULL)
@@ -5810,7 +5888,10 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
       irel.r_info = ELF_R_INFO (indx, howto->type);
       erel = ((Elf_External_Rel *) rel_hdr->contents
              + elf_section_data (output_section)->rel_count);
-      elf_swap_reloc_out (output_bfd, &irel, erel);
+      if (bed->s->swap_reloc_out)
+       (*bed->s->swap_reloc_out) (output_bfd, &irel, (bfd_byte *) erel);
+      else
+       elf_swap_reloc_out (output_bfd, &irel, erel);
     }
   else
     {
@@ -5822,7 +5903,10 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
       irela.r_addend = addend;
       erela = ((Elf_External_Rela *) rel_hdr->contents
               + elf_section_data (output_section)->rel_count);
-      elf_swap_reloca_out (output_bfd, &irela, erela);
+      if (bed->s->swap_reloca_out)
+       (*bed->s->swap_reloca_out) (output_bfd, &irela, (bfd_byte *) erela);
+      else
+       elf_swap_reloca_out (output_bfd, &irela, erela);
     }
 
   ++elf_section_data (output_section)->rel_count;
This page took 0.033187 seconds and 4 git commands to generate.