[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#508929: mklibs selects symbols from the wrong library



Frans Pop wrote:
That still gives me an error:
Traceback (most recent call last):
  File "/usr/bin/mklibs", line 509, in <module>
    library_symbols_used[lib].add(library_symbols[lib][name])
KeyError: 'strlongest@Base@unknown'
make[2]: *** [stamps/tree-netboot-stamp] Error 1

OK, let's try again. I've attached another patch with the obvious omission fixed. Unfortunately I don't have any libraries handy to test this. If this doesn't work for you then I'll see if I can reproduce the problem locally.

Andrew
---
 src/mklibs-readelf/elf.cpp      |   20 +++++++++++++++++---
 src/mklibs-readelf/elf.hpp      |    8 ++++++++
 src/mklibs-readelf/elf_data.hpp |    2 +-
 src/mklibs-readelf/main.cpp     |    3 ++-
 src/mklibs.py                   |   39 ++++++++++++++++++++++++---------------
 5 files changed, 52 insertions(+), 20 deletions(-)

Index: src/mklibs-readelf/elf.cpp
===================================================================
--- src/mklibs-readelf/elf.cpp.orig
+++ src/mklibs-readelf/elf.cpp
@@ -445,6 +445,14 @@ std::string symbol::get_version () const
   return "Base";
 }
 
+std::string symbol::get_version_file () const throw (std::bad_alloc)
+{
+  if (verneed)
+    return verneed->get_file();
+
+  return "unknown";
+}
+
 std::string symbol::get_name_version () const throw (std::bad_alloc)
 {
   std::string ver;
@@ -539,10 +547,12 @@ version_requirement_data<_class, _data>:
 
   char *act = reinterpret_cast<char *> (verneed) + aux;
 
+  file = convert<_data, typeof (verneed->vn_file)> () (verneed->vn_file);
+
   for (int i = 0; i < cnt; i++)
   {
     Vernaux *vernaux = reinterpret_cast<Vernaux *> (act);
-    entries.push_back(new version_requirement_entry_data<_class, _data> (vernaux));
+    entries.push_back(new version_requirement_entry_data<_class, _data> (this, vernaux));
     uint32_t next = convert<_data, typeof (vernaux->vna_next)> () (vernaux->vna_next);
     act += next;
   }
@@ -551,17 +561,21 @@ version_requirement_data<_class, _data>:
 template <typename _class, typename _data>
 void version_requirement_data<_class, _data>::update_string(const section_type<section_type_STRTAB> &section) throw (std::bad_alloc)
 {
+  file_string = section.get_string(file);
+
   for (std::vector<version_requirement_entry *>::iterator it = entries.begin(); it != entries.end(); ++it)
   {
     version_requirement_entry_data<_class, _data> &vernaux =
-      dynamic_cast<version_requirement_entry_data<_class, _data> &> (**it);
+      dynamic_cast<version_requirement_entry_data<_class, _data> &> (this, **it);
     vernaux.update_string(section);
   }
 }
 
 template <typename _class, typename _data>
-version_requirement_entry_data<_class, _data>::version_requirement_entry_data (Vernaux *vna) throw ()
+version_requirement_entry_data<_class, _data>::version_requirement_entry_data (const version_requirement_data<_class, _data> *parent, Vernaux *vna) throw ()
 {
+  this->parent = parent;
+
   flags = convert<_data, typeof (vna->vna_flags)> () (vna->vna_flags);
   other = convert<_data, typeof (vna->vna_other)> () (vna->vna_other);
   name  = convert<_data, typeof (vna->vna_name)> ()  (vna->vna_name);
Index: src/mklibs-readelf/elf.hpp
===================================================================
--- src/mklibs-readelf/elf.hpp.orig
+++ src/mklibs-readelf/elf.hpp
@@ -264,6 +264,7 @@ namespace Elf
       uint8_t get_type () const throw () { return type; }
       const std::string &get_name_string () const throw () { return name_string; }
       std::string get_version() const throw (std::bad_alloc);
+      std::string get_version_file() const throw (std::bad_alloc);
       uint16_t get_version_data() const throw () { return versym; }
       std::string get_name_version() const throw (std::bad_alloc);
 
@@ -306,9 +307,13 @@ namespace Elf
     public:
       virtual ~version_requirement () throw () { }
 
+      const std::string &get_file() const throw () { return file_string; }
       const std::vector<version_requirement_entry *> &get_entries () const throw () { return entries; }
 
     protected:
+      uint32_t file;
+
+      std::string file_string;
       std::vector<version_requirement_entry *> entries;
   };
 
@@ -319,8 +324,11 @@ namespace Elf
 
       uint16_t get_other () const throw () { return other; }
       const std::string &get_name() const throw () { return name_string; }
+      const std::string &get_file() const throw () { return parent->get_file(); }
 
     protected:
+      const version_requirement *parent;
+
       uint16_t flags;
       uint16_t other;
       uint32_t name;
Index: src/mklibs-readelf/elf_data.hpp
===================================================================
--- src/mklibs-readelf/elf_data.hpp.orig
+++ src/mklibs-readelf/elf_data.hpp
@@ -214,7 +214,7 @@ namespace Elf
       public:
         typedef typename _elfdef<_class>::Vernaux Vernaux;
 
-        version_requirement_entry_data (Vernaux *) throw ();
+        version_requirement_entry_data (const version_requirement_data<_class,_data> *, Vernaux *) throw ();
 
         void update_string(const section_type<section_type_STRTAB> &) throw (std::bad_alloc);
     };
Index: src/mklibs-readelf/main.cpp
===================================================================
--- src/mklibs-readelf/main.cpp.orig
+++ src/mklibs-readelf/main.cpp
@@ -95,7 +95,8 @@ static void process_symbols_undefined (c
       std::cout <<
         symbol->get_name_string () << ' ' <<
         (bind == STB_WEAK ? "True" : "False") << ' ' <<
-        symbol->get_version() << '\n';
+        symbol->get_version() << ' ' <<
+	symbol->get_version_file() << '\n';
   }
 }
 
Index: src/mklibs.py
===================================================================
--- src/mklibs.py.orig
+++ src/mklibs.py
@@ -139,8 +139,8 @@ def undefined_symbols(obj):
     result = []
     output = command("mklibs-readelf", "--print-symbols-undefined", obj)
     for line in output:
-        name, weak_string, version = line.split()[:3]
-        result.append(UndefinedSymbol(name, bool(eval(weak_string)), version))
+        name, weak_string, version, library = line.split()[:4]
+        result.append(UndefinedSymbol(name, bool(eval(weak_string)), "%s@%s" % (version, library)))
     return result
 
 class ProvidedSymbol(Symbol):
@@ -149,14 +149,16 @@ class ProvidedSymbol(Symbol):
         self.default_version = default_version
 
     def base_names(self):
-        if self.default_version and self.version != "Base":
-            return ["%s@%s" % (self.name, self.version), "%s@Base" % self.name]
+        ver, lib = self.version.split('@', 1)[:2]
+        if self.default_version and ver != "Base":
+            return ["%s@%s" % (self.name, self.version), "%s@Base@%s" % (self.name, lib)]
         return ["%s@%s" % (self.name, self.version)]
 
     def linker_name(self):
-        if self.default_version or self.version == "Base":
+        ver, lib = self.version.split('@', 1)[:2]
+        if self.default_version or ver == "Base":
             return self.name
-        return "%s@%s" % (self.name, self.version)
+        return "%s@%s" % (self.name, ver)
 
 # Return a set of symbols provided by a library
 def provided_symbols(obj):
@@ -167,7 +169,7 @@ def provided_symbols(obj):
     output = command("mklibs-readelf", "--print-symbols-provided", obj)
     for line in output:
         name, weak, version, default_version_string = line.split()[:4]
-        result.append(ProvidedSymbol(name, version, bool(eval(default_version_string))))
+        result.append(ProvidedSymbol(name, "%s@%s" % (version, extract_soname(obj)), bool(eval(default_version_string))))
     return result
     
 # Return real target of a symlink
@@ -208,10 +210,17 @@ def find_pic_map(lib):
                 return resolve_link(file)
     return ""
 
+soname_cache = {}
 def extract_soname(so_file):
+    name = soname_cache.get(so_file)
+    if name is not None:
+        return name
     soname_data = command("mklibs-readelf", "--print-soname", so_file)
     if soname_data:
-        return soname_data.pop()
+        name = soname_data.pop()
+        soname_cache[so_file] = name
+        return name
+    soname_cache[so_file] = ""
     return ""
 
 def usage(was_err):
@@ -479,15 +488,15 @@ while 1:
         for symbol in symbols:
             for name in symbol.base_names():
                 if name in symbol_provider:
-                    # in doubt, prefer symbols from libc
-                    if re.match("^libc[\.-]", library):
-                        library_symbols[library][name] = symbol
-                        symbol_provider[name] = library
-                    else:
-                        debug(DEBUG_SPAM, "duplicate symbol %s in %s and %s" % (symbol, symbol_provider[name], library))
+                    debug(DEBUG_SPAM, "duplicate symbol %s in %s and %s" % (symbol, symbol_provider[name], library))
                 else:
                     library_symbols[library][name] = symbol
                     symbol_provider[name] = library
+		# save the first library containing each symbol (for matching library 'unknown')
+		nolib_name = "%s@unknown" % name.rsplit('@', 1)[0]
+		if not nolib_name in symbol_provider:
+		    library_symbols[library][nolib_name] = symbol
+		    symbol_provider[nolib_name] = library
 
     # which symbols are actually used from each lib
     for name in needed_symbols:
@@ -540,7 +549,7 @@ while 1:
                 # may segfault in ptmalloc_init due to undefined weak reference
                 extra_pre_obj.append(sysroot + libc_extras_dir + "/soinit.o")
                 extra_post_obj.append(sysroot + libc_extras_dir + "/sofini.o")
-                symbols.add(ProvidedSymbol('__dso_handle', 'Base', True))
+                symbols.add(ProvidedSymbol('__dso_handle', 'Base@%s' % soname, True))
 
             map_file = find_pic_map(library)
             if map_file:

Reply to: