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

Bug#508929: marked as done (mklibs selects symbols from the wrong library)



Your message dated Wed, 06 May 2009 12:02:05 +0000
with message-id <E1M1fp7-0008Gz-JV@ries.debian.org>
and subject line Bug#508929: fixed in mklibs 0.1.27
has caused the Debian Bug report #508929,
regarding mklibs selects symbols from the wrong library
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
508929: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=508929
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: mklibs
Tags: patch

The problem is that mklibs selects either the first symbol of the correct name, or the one in libc, if there is one. It completely disregards the information left by the linker defining where each symbol *should* come from.

The dynamic linker does use this data, so it looks for symbols in specific libraries and complains if they aren't there.

To reproduce the problem:

---8<------------->8------
#include <stdio.h>
#include <math.h>

int main(void)
{
	double x, y, n;

	x = -14.87654321;
	y = modf( x, &n );
	printf("%f, %f, %f\n", x, y, n);

	return 0;
}
---8<------------->8------

gcc modf_test.c -lm
mklibs -d result a.out

Then result/libm.so.6 contains no symbols, and modf is present in result/libc.so.6. This issue may only exist some platforms - mips-linux-gnu is the one with which I have observed the problem. This is because the modf symbol is present in both libm *and* libc, and mklibs always prefers libc.

The problem can be worked around by means of LD_PRELOAD=libm.so (or whatever library), because then the symbol is resolved early, and the dynamic linker does not have to search for it elsewhere. Note that doing this only works if all symbols of the same name have compatible definitions. Otherwise, the program will be silently broken.

This patch modifies mklibs-readelf to extract the library name associated with each undefined symbol (in addition to the version it already gets).

mklibs.py then treats each symbol as a triplet, rather than a pair:

  printf@GLIBC_2.0 -> printf@GLIBC_2.0@libc.so.6

Each symbol can now only match against one library. This should produce the same mapping that the dynamic linker would use (minus LD_PRELOAD).

Andrew Stubbs
---
 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                   |   34 +++++++++++++++++++---------------
 5 files changed, 47 insertions(+), 20 deletions(-)

Index: src/mklibs-readelf/elf.cpp
===================================================================
--- src/mklibs-readelf/elf.cpp.orig	2008-12-16 16:48:07.000000000 +0000
+++ src/mklibs-readelf/elf.cpp	2008-12-16 17:43:42.000000000 +0000
@@ -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	2008-12-16 16:48:07.000000000 +0000
+++ src/mklibs-readelf/elf.hpp	2008-12-16 17:43:42.000000000 +0000
@@ -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	2008-12-16 16:48:07.000000000 +0000
+++ src/mklibs-readelf/elf_data.hpp	2008-12-16 17:43:42.000000000 +0000
@@ -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	2008-12-16 16:48:07.000000000 +0000
+++ src/mklibs-readelf/main.cpp	2008-12-16 17:43:42.000000000 +0000
@@ -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	2008-12-16 16:48:07.000000000 +0000
+++ src/mklibs.py	2008-12-16 18:07:45.000000000 +0000
@@ -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):
+    for file, name in soname_cache:
+      if file == so_file:
+        return name
     soname_data = command("mklibs-readelf", "--print-soname", so_file)
     if soname_data:
-        return soname_data.pop()
+        name = soname_data.pop()
+        soname_cache.append((so_file, name))
+        return name
+    soname_cache.append((so_file, ""))
     return ""
 
 def usage(was_err):
@@ -479,12 +488,7 @@ 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
@@ -540,7 +544,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:

--- End Message ---
--- Begin Message ---
Source: mklibs
Source-Version: 0.1.27

We believe that the bug you reported is fixed in the latest version of
mklibs, which is due to be installed in the Debian FTP archive:

mklibs-copy_0.1.27_i386.deb
  to pool/main/m/mklibs/mklibs-copy_0.1.27_i386.deb
mklibs_0.1.27.dsc
  to pool/main/m/mklibs/mklibs_0.1.27.dsc
mklibs_0.1.27.tar.gz
  to pool/main/m/mklibs/mklibs_0.1.27.tar.gz
mklibs_0.1.27_all.deb
  to pool/main/m/mklibs/mklibs_0.1.27_all.deb



A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to 508929@bugs.debian.org,
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Bastian Blank <waldi@debian.org> (supplier of updated mklibs package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing ftpmaster@debian.org)


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Format: 1.8
Date: Wed, 06 May 2009 13:56:04 +0200
Source: mklibs
Binary: mklibs mklibs-copy
Architecture: source all i386
Version: 0.1.27
Distribution: unstable
Urgency: low
Maintainer: Debian Install System Team <debian-boot@lists.debian.org>
Changed-By: Bastian Blank <waldi@debian.org>
Description: 
 mklibs     - Shared library reduction script
 mklibs-copy - Shared library reduction script
Closes: 469070 499744 505025 508929 518088
Changes: 
 mklibs (0.1.27) unstable; urgency=low
 .
   [ Joey Hess ]
   * Apply patches from Joseph S. Myers (closes: #469070):
     - mklibs-readelf: Uninitialized data fix
     - mklibs-readelf: Endian fix
     - mklibs: Add --sysroot, to locate all libraries and other related input
       files relative to a specified root directory rather than /.
     - mklibs: Add --gcc-options and --libdir options as well.
     - mklibs: Correct diagnostic text when symbol cannot be found.
     - mklibs: Ignore missing symbols from libthread_db, which are defined
       in the application that uses it.
   * Document --root in the man page.
 .
   [ Frans Pop ]
   * Apply patches from Joseph S. Myers:
     - Ignore the fact that symbol __gnu_local_gp is undefined for mips as it
       is defined by the linker. Thanks to Joseph S. Myers. Closes: #499744.
   * Remove myself as uploader.
 .
   [ Martin Michlmayr ]
   * mklibs-readelf: add missing header to avoid build error with GCC 4.4.
     Closes: #505025.
 .
   [ Bastian Blank ]
   * Support file definitions in version requirements. Based on patch by Andrew
     Stubbs <ams@codesourcery.com>. (closes: #508929)
   * Various cleanups.
   * Ignore symbols with empty names. (closes: #518088)
Checksums-Sha1: 
 e7b3c9c88e570c512290cf905745d1b6e4821fb1 969 mklibs_0.1.27.dsc
 bbf12828d09af12df501b5a748ff544c2bf3e25a 113602 mklibs_0.1.27.tar.gz
 d0b6804b85de9a532a839edc717f5e590f8a31bc 12988 mklibs_0.1.27_all.deb
 c7106ccb17e136d678a9d677d9b3da16bdb89bc5 44700 mklibs-copy_0.1.27_i386.deb
Checksums-Sha256: 
 1d6722106dd092c22e9839b668ae1a7dfb29036a3322f61b993d7e6944041f93 969 mklibs_0.1.27.dsc
 9eb44b5106f4c0d243c3c28e9c7f0d21667a6207ea32b2508936591cbed2519d 113602 mklibs_0.1.27.tar.gz
 9827873656f4bc7f7e74857e9b8c8fee94d0a0c7ed1b460114c94b2ad0631d24 12988 mklibs_0.1.27_all.deb
 f4e91935144cff23f1e53e77562f0e85b795b42d0d38b3da24ed0701a21a28a0 44700 mklibs-copy_0.1.27_i386.deb
Files: 
 c0bfa4e721e2c755ec3bf37d884c146e 969 devel optional mklibs_0.1.27.dsc
 ce906873efcf84c401479e9c10279660 113602 devel optional mklibs_0.1.27.tar.gz
 c55b104408f866f03dde78c1f98cfc38 12988 devel optional mklibs_0.1.27_all.deb
 5769bcf8e7eb2e61d148f250d4affaa7 44700 devel optional mklibs-copy_0.1.27_i386.deb

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAkoBevAACgkQLkAIIn9ODhHgRwCgwtG5By62ROiWiQlqHgLYPFX2
Qm4AoLIkyC1t1Q5C+ARLI81OMgk4ldEb
=L9ab
-----END PGP SIGNATURE-----



--- End Message ---

Reply to: