2000-07-19 H.J. Lu <hjl@gnu.org>
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 20 Jul 2000 03:16:18 +0000 (03:16 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Thu, 20 Jul 2000 03:16:18 +0000 (03:16 +0000)
* bfd-in.h (bfd_elf_set_dt_needed_soname): New.
* bfd-in2.h: Rebuild.

* elf-bfd.h (elf_obj_tdata): Add dt_soname.
(elf_dt_soname): New.

* elf.c (bfd_elf_set_dt_needed_soname): New.

* elflink.h (elf_link_add_object_symbols): Add the DT_NEEDED
entry if the shared object loaded by DT_NEEDED is used to
resolve the reference in a regular object.

bfd/ChangeLog
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/elf-bfd.h
bfd/elf.c
bfd/elflink.h

index 9836baf77631093761080b10e5cd7b1661e72ed9..210d6ad7476111da62f112a62b360456caa8ec4a 100644 (file)
@@ -1,3 +1,17 @@
+2000-07-19  H.J. Lu  <hjl@gnu.org>
+
+       * bfd-in.h (bfd_elf_set_dt_needed_soname): New.
+       * bfd-in2.h: Rebuild.
+
+       * elf-bfd.h (elf_obj_tdata): Add dt_soname.
+       (elf_dt_soname): New.
+
+       * elf.c (bfd_elf_set_dt_needed_soname): New.
+
+       * elflink.h (elf_link_add_object_symbols): Add the DT_NEEDED
+       entry if the shared object loaded by DT_NEEDED is used to
+       resolve the reference in a regular object.
+
 2000-07-19  H.J. Lu  <hjl@gnu.org>
 
        * elf.c (_bfd_elf_print_private_bfd_data): Handle DT_CONFIG,
index 79e483d51d464305e941a04ede2fb9563ad02624..f8bba47d14de1f767ac066dd6706e9f5f83adb83 100644 (file)
@@ -627,6 +627,7 @@ extern boolean bfd_elf64_size_dynamic_sections
           const char * const *, struct bfd_link_info *, struct sec **,
           struct bfd_elf_version_tree *));
 extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
+extern void bfd_elf_set_dt_needed_soname PARAMS ((bfd *, const char *));
 extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
 
 /* Return an upper bound on the number of bytes required to store a
index 5d139db494675891d50611b1007f643b4890bccc..1137076f2b2f25faa692d60bf21c555799b9bf37 100644 (file)
@@ -627,6 +627,7 @@ extern boolean bfd_elf64_size_dynamic_sections
           const char * const *, struct bfd_link_info *, struct sec **,
           struct bfd_elf_version_tree *));
 extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
+extern void bfd_elf_set_dt_needed_soname PARAMS ((bfd *, const char *));
 extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
 
 /* Return an upper bound on the number of bytes required to store a
index 2980f0f39895c646d0c698d7cf2398160a2fa1da..0ef27ea9fc2bd95886209c6192013684c1fee9c7 100644 (file)
@@ -838,6 +838,14 @@ struct elf_obj_tdata
      one.  */
   const char *dt_name;
 
+  /* When a reference in a regular object is resolved by a shared
+     object is loaded into via the DT_NEEDED entries by the linker
+     ELF emulation code, we need to add the shared object to the
+     DT_NEEDED list of the resulting binary to indicate the dependency
+     as if the -l option is passed to the linker. This field holds the
+     name of the loaded shared object. */
+  const char *dt_soname;
+
   /* Irix 5 often screws up the symbol table, sorting local symbols
      after global symbols.  This flag is set if the symbol table in
      this BFD appears to be screwed up.  If it is, we ignore the
@@ -915,6 +923,7 @@ struct elf_obj_tdata
 #define elf_local_got_offsets(bfd) (elf_tdata(bfd) -> local_got.offsets)
 #define elf_local_ptr_offsets(bfd) (elf_tdata(bfd) -> linker_section_pointers)
 #define elf_dt_name(bfd)       (elf_tdata(bfd) -> dt_name)
+#define elf_dt_soname(bfd)     (elf_tdata(bfd) -> dt_soname)
 #define elf_bad_symtab(bfd)    (elf_tdata(bfd) -> bad_symtab)
 #define elf_flags_init(bfd)    (elf_tdata(bfd) -> flags_init)
 #define elf_linker_section(bfd,n) (elf_tdata(bfd) -> linker_section[(int)n])
index 523dd34b5eb895babc0290c03b14b5f331a74a1b..d394f348cb0a8c2d54ec9fcd1ecf3d293a9d107d 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1050,6 +1050,16 @@ bfd_elf_set_dt_needed_name (abfd, name)
     elf_dt_name (abfd) = name;
 }
 
+void
+bfd_elf_set_dt_needed_soname (abfd, name)
+     bfd *abfd;
+     const char *name;
+{
+  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+      && bfd_get_format (abfd) == bfd_object)
+    elf_dt_soname (abfd) = name;
+}
+
 /* Get the list of DT_NEEDED entries for a link.  This is a hook for
    the linker ELF emulation code.  */
 
index b1f20d7708afb869ce23412fe4f776461d17e2ce..7fa35a936ce0eee2f13a93babdf84117ddbe89bc 100644 (file)
@@ -890,6 +890,7 @@ elf_link_add_object_symbols (abfd, info)
   Elf_External_Sym *esym;
   Elf_External_Sym *esymend;
   struct elf_backend_data *bed;
+  boolean dt_needed;
 
   bed = get_elf_backend_data (abfd);
   add_symbol_hook = bed->elf_add_symbol_hook;
@@ -1049,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
@@ -1085,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)
@@ -1863,6 +1871,53 @@ elf_link_add_object_symbols (abfd, info)
                (*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;
+           }
        }
     }