* libelf.h (struct elf_link_hash_table): Add needed field. Remove
authorIan Lance Taylor <ian@airs.com>
Tue, 4 Jul 1995 16:54:49 +0000 (16:54 +0000)
committerIan Lance Taylor <ian@airs.com>
Tue, 4 Jul 1995 16:54:49 +0000 (16:54 +0000)
saw_needed field.
* elfcode.h (elf_link_add_object_symbols): If elf_dt_needed_name
is an empty string, don't make a DT_NEEDED entry in the output
file.  Record all DT_NEEDED entries found in input dynamic
objects.
(elf_link_output_extsym): Don't check saw_needed when issuing
warnings.
* elf.c (_bfd_elf_link_hash_table_init): Initialize needed, not
saw_needed.
(bfd_elf_get_needed_list): New function.
* bfd-in.h (struct bfd_elf_link_needed_list): Define.
(bfd_elf_get_needed_list): Define.
* bfd-in2.h: Rebuild.
PR 7083.

bfd/ChangeLog
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/elf.c
bfd/elfcode.h
bfd/libelf.h

index 2f0c1b71f3fbe7b5abddba38386cfdd6812013fb..88de922c3350931fc2817e62d2d7fd1ff5c28487 100644 (file)
@@ -1,5 +1,20 @@
 Tue Jul  4 12:22:21 1995  Ian Lance Taylor  <ian@cygnus.com>
 
+       * libelf.h (struct elf_link_hash_table): Add needed field.  Remove
+       saw_needed field.
+       * elfcode.h (elf_link_add_object_symbols): If elf_dt_needed_name
+       is an empty string, don't make a DT_NEEDED entry in the output
+       file.  Record all DT_NEEDED entries found in input dynamic
+       objects.
+       (elf_link_output_extsym): Don't check saw_needed when issuing
+       warnings.
+       * elf.c (_bfd_elf_link_hash_table_init): Initialize needed, not
+       saw_needed.
+       (bfd_elf_get_needed_list): New function.
+       * bfd-in.h (struct bfd_elf_link_needed_list): Define.
+       (bfd_elf_get_needed_list): Define.
+       * bfd-in2.h: Rebuild.
+
        * ecoff.c (_bfd_ecoff_find_nearest_line): Also initialize
        find_buffer and fdrtab_len fields of newly allocated
        find_line_info structure.
index 7af736c28db92813a47c997c22bed4e49aceef47..151e824beeafe6fb1b61faf040592f2a23f2665b 100644 (file)
@@ -482,6 +482,9 @@ typedef struct _bfd_link_stack_heap bfd_link_stack_heap;
 
 /* END OF PE STUFF */
 
+extern enum bfd_link_subsystem NT_subsystem;
+extern bfd_link_stack_heap NT_stack_heap;
+
 /* Cast from const char * to char * so that caller can assign to
    a char * without a warning.  */
 #define bfd_get_filename(abfd) ((char *) (abfd)->filename)
@@ -592,6 +595,14 @@ extern boolean bfd_elf32_record_link_assignment
   PARAMS ((bfd *, struct bfd_link_info *, const char *));
 extern boolean bfd_elf64_record_link_assignment
   PARAMS ((bfd *, struct bfd_link_info *, const char *));
+struct bfd_elf_link_needed_list
+{
+  struct bfd_elf_link_needed_list *next;
+  bfd *by;
+  const char *name;
+};
+extern struct bfd_elf_link_needed_list *bfd_elf_get_needed_list
+  PARAMS ((bfd *, struct bfd_link_info *));
 extern boolean bfd_elf32_size_dynamic_sections
   PARAMS ((bfd *, const char *, const char *, boolean,
           struct bfd_link_info *, struct sec **));
@@ -614,11 +625,3 @@ extern boolean bfd_linux_size_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 
 /* And more from the source.  */
-
-/* provide storage for subsystem, stack and heap data which may have been
-   passed in on the command line.  Ld puts this data into a bfd_link_info
-   struct which ultimately gets passed in to the bfd.  When it arrives, copy
-   it to the following struct so that the data will be available in coffcode.h
-   where it is needed.  The typedef's used are defined in bfd.h */
-enum   bfd_link_subsystem  NT_subsystem;
-bfd_link_stack_heap NT_stack_heap;
index b197e424a8cb8ec7428b980233d061e8b880da45..1b0ba63f689913bf386ecd62249695ac17149765 100644 (file)
@@ -595,6 +595,14 @@ extern boolean bfd_elf32_record_link_assignment
   PARAMS ((bfd *, struct bfd_link_info *, const char *));
 extern boolean bfd_elf64_record_link_assignment
   PARAMS ((bfd *, struct bfd_link_info *, const char *));
+struct bfd_elf_link_needed_list
+{
+  struct bfd_elf_link_needed_list *next;
+  bfd *by;
+  const char *name;
+};
+extern struct bfd_elf_link_needed_list *bfd_elf_get_needed_list
+  PARAMS ((bfd *, struct bfd_link_info *));
 extern boolean bfd_elf32_size_dynamic_sections
   PARAMS ((bfd *, const char *, const char *, boolean,
           struct bfd_link_info *, struct sec **));
index 6fece72e56d8dd26caef7dbf3cf2652822ab3435..2ff754361adb18bdf55cc0ab4f73eda4a19f763d 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -122,14 +122,14 @@ elf_get_str_section (abfd, shindex)
   if (i_shdrp == 0 || i_shdrp[shindex] == 0)
     return 0;
 
-  shstrtab = i_shdrp[shindex]->rawdata;
+  shstrtab = (char *) i_shdrp[shindex]->contents;
   if (shstrtab == NULL)
     {
       /* No cached one, attempt to read, and cache what we read. */
       offset = i_shdrp[shindex]->sh_offset;
       shstrtabsize = i_shdrp[shindex]->sh_size;
       shstrtab = elf_read (abfd, offset, shstrtabsize);
-      i_shdrp[shindex]->rawdata = (void *) shstrtab;
+      i_shdrp[shindex]->contents = (PTR) shstrtab;
     }
   return shstrtab;
 }
@@ -147,15 +147,15 @@ elf_string_from_elf_section (abfd, shindex, strindex)
 
   hdr = elf_elfsections (abfd)[shindex];
 
-  if (!hdr->rawdata
+  if (hdr->contents == NULL
       && elf_get_str_section (abfd, shindex) == NULL)
     return NULL;
 
-  return ((char *) hdr->rawdata) + strindex;
+  return ((char *) hdr->contents) + strindex;
 }
 
 /* Make a BFD section from an ELF section.  We store a pointer to the
-   BFD section in the rawdata field of the header.  */
+   BFD section in the bfd_section field of the header.  */
 
 boolean
 _bfd_elf_make_section_from_shdr (abfd, hdr, name)
@@ -166,9 +166,10 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
   asection *newsect;
   flagword flags;
 
-  if (hdr->rawdata != NULL)
+  if (hdr->bfd_section != NULL)
     {
-      BFD_ASSERT (strcmp (name, ((asection *) hdr->rawdata)->name) == 0);
+      BFD_ASSERT (strcmp (name,
+                         bfd_get_section_name (abfd, hdr->bfd_section)) == 0);
       return true;
     }
 
@@ -210,7 +211,7 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
   if (! bfd_set_section_flags (abfd, newsect, flags))
     return false;
 
-  hdr->rawdata = (PTR) newsect;
+  hdr->bfd_section = newsect;
   elf_section_data (newsect)->this_hdr = *hdr;
 
   return true;
@@ -301,6 +302,45 @@ bfd_elf_generic_reloc (abfd,
   return bfd_reloc_continue;
 }
 \f
+/* Display ELF-specific fields of a symbol.  */
+void
+bfd_elf_print_symbol (ignore_abfd, filep, symbol, how)
+     bfd *ignore_abfd;
+     PTR filep;
+     asymbol *symbol;
+     bfd_print_symbol_type how;
+{
+  FILE *file = (FILE *) filep;
+  switch (how)
+    {
+    case bfd_print_symbol_name:
+      fprintf (file, "%s", symbol->name);
+      break;
+    case bfd_print_symbol_more:
+      fprintf (file, "elf ");
+      fprintf_vma (file, symbol->value);
+      fprintf (file, " %lx", (long) symbol->flags);
+      break;
+    case bfd_print_symbol_all:
+      {
+       CONST char *section_name;
+       section_name = symbol->section ? symbol->section->name : "(*none*)";
+       bfd_print_symbol_vandf ((PTR) file, symbol);
+       fprintf (file, " %s\t", section_name);
+       /* Print the "other" value for a symbol.  For common symbols,
+          we've already printed the size; now print the alignment.
+          For other symbols, we have no specified alignment, and
+          we've printed the address; now print the size.  */
+       fprintf_vma (file,
+                    (bfd_is_com_section (symbol->section)
+                     ? ((elf_symbol_type *) symbol)->internal_elf_sym.st_value
+                     : ((elf_symbol_type *) symbol)->internal_elf_sym.st_size));
+       fprintf (file, " %s", symbol->name);
+      }
+      break;
+    }
+}
+\f
 /* Create an entry in an ELF linker hash table.  */
 
 struct bfd_hash_entry *
@@ -334,7 +374,8 @@ _bfd_elf_link_hash_newfunc (entry, table, string)
       ret->dynindx = -1;
       ret->dynstr_index = 0;
       ret->weakdef = NULL;
-      ret->copy_offset = 0;
+      ret->got_offset = (bfd_vma) -1;
+      ret->plt_offset = (bfd_vma) -1;
       ret->type = STT_NOTYPE;
       ret->elf_link_hash_flags = 0;
     }
@@ -352,10 +393,13 @@ _bfd_elf_link_hash_table_init (table, abfd, newfunc)
                                                struct bfd_hash_table *,
                                                const char *));
 {
+  table->dynamic_sections_created = false;
   table->dynobj = NULL;
-  table->dynsymcount = 0;
+  /* The first dynamic symbol is a dummy.  */
+  table->dynsymcount = 1;
   table->dynstr = NULL;
   table->bucketcount = 0;
+  table->needed = NULL;
   return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
 }
 
@@ -386,7 +430,8 @@ _bfd_elf_link_hash_table_create (abfd)
 
 /* This is a hook for the ELF emulation code in the generic linker to
    tell the backend linker what file name to use for the DT_NEEDED
-   entry for a dynamic object.  */
+   entry for a dynamic object.  The generic linker passes name as an
+   empty string to indicate that no DT_NEEDED entry should be made.  */
 
 void
 bfd_elf_set_dt_needed_name (abfd, name)
@@ -395,3 +440,13 @@ bfd_elf_set_dt_needed_name (abfd, name)
 {
   elf_dt_needed_name (abfd) = name;
 }
+
+/* Get the list of DT_NEEDED entries for a link.  */
+
+struct bfd_elf_link_needed_list *
+bfd_elf_get_needed_list (abfd, info)
+     bfd *abfd;
+     struct bfd_link_info *info;
+{
+  return elf_hash_table (info)->needed;
+}
index 2ce8bed4ed2c0ae3cea95ee065ea89896e3fcb80..e0f1b9c1ec2d7161e71ea3f6ace6654275925d4e 100644 (file)
@@ -4297,6 +4297,7 @@ elf_link_add_object_symbols (abfd, info)
   else
     {
       asection *s;
+      boolean add_needed;
       const char *name;
       bfd_size_type oldsize;
       bfd_size_type strindex;
@@ -4317,15 +4318,24 @@ elf_link_add_object_symbols (abfd, info)
         object.  If the object has a DT_SONAME entry, we use it.
         Otherwise, if the generic linker stuck something in
         elf_dt_needed_name, we use that.  Otherwise, we just use the
-        file name.  */
+        file name.  If the generic linker put a null string into
+        elf_dt_needed_name, we don't make a DT_NEEDED entry at all,
+        even if there is a DT_SONAME entry.  */
+      add_needed = true;
       name = bfd_get_filename (abfd);
       if (elf_dt_needed_name (abfd) != NULL)
-       name = elf_dt_needed_name (abfd);
+       {
+         name = elf_dt_needed_name (abfd);
+         if (*name == '\0')
+           add_needed = false;
+       }
       s = bfd_get_section_by_name (abfd, ".dynamic");
       if (s != NULL)
        {
          Elf_External_Dyn *extdyn;
          Elf_External_Dyn *extdynend;
+         int elfsec;
+         unsigned long link;
 
          dynbuf = (Elf_External_Dyn *) malloc (s->_raw_size);
          if (dynbuf == NULL)
@@ -4338,6 +4348,11 @@ elf_link_add_object_symbols (abfd, info)
                                          (file_ptr) 0, s->_raw_size))
            goto error_return;
 
+         elfsec = elf_section_from_bfd_section (abfd, s);
+         if (elfsec == -1)
+           goto error_return;
+         link = elf_elfsections (abfd)[elfsec]->sh_link;
+
          extdyn = dynbuf;
          extdynend = extdyn + s->_raw_size / sizeof (Elf_External_Dyn);
          for (; extdyn < extdynend; extdyn++)
@@ -4345,22 +4360,37 @@ elf_link_add_object_symbols (abfd, info)
              Elf_Internal_Dyn dyn;
 
              elf_swap_dyn_in (abfd, extdyn, &dyn);
-             if (dyn.d_tag == DT_SONAME)
+             if (add_needed && dyn.d_tag == DT_SONAME)
                {
-                 int elfsec;
-                 unsigned long link;
-
-                 elfsec = elf_section_from_bfd_section (abfd, s);
-                 if (elfsec == -1)
-                   goto error_return;
-                 link = elf_elfsections (abfd)[elfsec]->sh_link;
                  name = elf_string_from_elf_section (abfd, link,
                                                      dyn.d_un.d_val);
                  if (name == NULL)
                    goto error_return;
                }
              if (dyn.d_tag == DT_NEEDED)
-               elf_hash_table (info)->saw_needed = true;
+               {
+                 struct bfd_elf_link_needed_list *n, **pn;
+                 char *fnm, *anm;
+
+                 n = bfd_alloc (abfd,
+                                sizeof (struct bfd_elf_link_needed_list));
+                 fnm = elf_string_from_elf_section (abfd, link,
+                                                    dyn.d_un.d_val);
+                 if (n == NULL || fnm == NULL)
+                   goto error_return;
+                 anm = bfd_alloc (abfd, strlen (fnm) + 1);
+                 if (anm == NULL)
+                   goto error_return;
+                 strcpy (anm, fnm);
+                 n->name = anm;
+                 n->by = abfd;
+                 n->next = NULL;
+                 for (pn = &elf_hash_table (info)->needed;
+                      *pn != NULL;
+                      pn = &(*pn)->next)
+                   ;
+                 *pn = n;
+               }
            }
 
          free (dynbuf);
@@ -4384,46 +4414,51 @@ elf_link_add_object_symbols (abfd, info)
            goto error_return;
        }
 
-      /* Add a DT_NEEDED entry for this dynamic object.  */
-      oldsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
-      strindex = _bfd_stringtab_add (elf_hash_table (info)->dynstr, name,
-                                    true, false);
-      if (strindex == (bfd_size_type) -1)
-       goto error_return;
-
-      if (oldsize == _bfd_stringtab_size (elf_hash_table (info)->dynstr))
+      if (add_needed)
        {
-         asection *sdyn;
-         Elf_External_Dyn *dyncon, *dynconend;
-
-         /* The hash table size did not change, which means that the
-             dynamic object name was already entered.  If we have
-             already included this dynamic object in the link, just
-             ignore it.  There is no reason to include a particular
-             dynamic object more than once.  */
-         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;
+         /* Add a DT_NEEDED entry for this dynamic object.  */
+         oldsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
+         strindex = _bfd_stringtab_add (elf_hash_table (info)->dynstr, name,
+                                        true, false);
+         if (strindex == (bfd_size_type) -1)
+           goto error_return;
 
-             elf_swap_dyn_in (elf_hash_table (info)->dynobj, dyncon, &dyn);
-             if (dyn.d_tag == DT_NEEDED
-                 && dyn.d_un.d_val == strindex)
+         if (oldsize == _bfd_stringtab_size (elf_hash_table (info)->dynstr))
+           {
+             asection *sdyn;
+             Elf_External_Dyn *dyncon, *dynconend;
+
+             /* The hash table size did not change, which means that
+                the dynamic object name was already entered.  If we
+                have already included this dynamic object in the
+                link, just ignore it.  There is no reason to include
+                a particular dynamic object more than once.  */
+             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++)
                {
-                 if (buf != NULL)
-                   free (buf);
-                 return true;
+                 Elf_Internal_Dyn dyn;
+
+                 elf_swap_dyn_in (elf_hash_table (info)->dynobj, dyncon,
+                                  &dyn);
+                 if (dyn.d_tag == DT_NEEDED
+                     && dyn.d_un.d_val == strindex)
+                   {
+                     if (buf != NULL)
+                       free (buf);
+                     return true;
+                   }
                }
            }
-       }
 
-      if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
-       goto error_return;
+         if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
+           goto error_return;
+       }
     }
 
   if (bfd_seek (abfd,
@@ -6237,18 +6272,9 @@ elf_link_output_extsym (h, data)
      linker will complain that the symbol is undefined when the
      program is run.  We don't have to worry about symbols that are
      referenced by regular files, because we will already have issued
-     warnings for them.
-
-     FIXME: If we are linking against an object which uses DT_NEEDED,
-     we don't give this warning, because it might be the case that the
-     needed dynamic object will define the symbols.  Unfortunately,
-     this makes this type of check much less useful, but the only way
-     to fix it would be to locate the needed object and read its
-     symbol table.  That seems like a real waste of time just to give
-     better error messages.  */
+     warnings for them.  */
   if (! finfo->info->relocateable
       && ! finfo->info->shared
-      && ! elf_hash_table (finfo->info)->saw_needed
       && h->root.type == bfd_link_hash_undefined
       && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0
       && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
index 28b9c9e2347ff1dadc4d62af91a459d9aab81a18..98d77b2a55e2c89790bca5916c7fe166bd4eac6e 100644 (file)
@@ -144,10 +144,9 @@ struct elf_link_hash_table
   /* The number of buckets in the hash table in the .hash section.
      This is based on the number of dynamic symbols.  */
   size_t bucketcount;
-  /* Whether we are linking against a dynamic object which has a
-     DT_NEEDED entry in the .dynamic section.  This may need to become
-     a list of DT_NEEDED entries.  */
-  boolean saw_needed;
+  /* A linked list of DT_NEEDED names found in dynamic objects
+     included in the link.  */
+  struct bfd_elf_link_needed_list *needed;
 };
 
 /* Look up an entry in an ELF linker hash table.  */