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

Bug#433874: potential patch for this bug



Attached is a patch adding symbol versioning to mklibs. Most of the work on
this was done by waldi, I contributed nasty modifications to mklibs.py that
work around strange linker behavior (described in #443252).

This version of mklibs is able to reduce d-i, but some fixed packages
are needed first:

* cdebconf-entropy (0.5) (uploaded)
* cdebconf (0.121) (uploaded)
* newt #443248

This is due to it being less forgiving of packages that indirectly link to
shared libraries than the previous version. It could be hacked to get closer
to the old behavior, but it seemed doable to fix these packages instead.
Unless there are a lot more things I don't know about. (This may make the d-i
build process slightly more fragile going forward..)

This is the part of the patch I am least happy with:
-            if not is_weak:
-                raise "Unresolvable symbol " + symbol
+           if not is_weak:
+               # XXX horrible workaround for #443252
+               if symbol_versions[re.sub("@.*", "", symbol)] == 1:
+                   debug(DEBUG_VERBOSE, "Ignoring potentially unresolvable",
+                       symbol, "since there is exactly one version")
+               else:
+                    raise "Unresolvable symbol " + symbol

The assumption here is that, if there is an unresolvable versioned symbol,
and we know that exactly one version of the symbol is provided by the
libraries, then we've reached a situation like described in #443252.

One example of where this assumption would fail: If a binary was linked
to symbol@GLIBC_2.4 and the d-i build environment had an old libc that
only provided symbol@GLIBC_2.1, mklibs would incorrectly assume the symbol
was provided. Of course, the old version of mklibs also failed to detect
this kind of version skew (that's what this bug is all about); at least
with my patch mklibs is able to warn of it.

I haven't actually tested this patched mklibs on sparc, alpha, or s390
to see if it adds the currently missing symbol versions for those arches.
Could someone with one of those arches handy try it?

-- 
see shy jo
diff -ur old/mklibs-0.1.24/debian/changelog mklibs-0.1.25/debian/changelog
--- old/mklibs-0.1.24/debian/changelog	2007-07-16 17:01:26.000000000 -0400
+++ mklibs-0.1.25/debian/changelog	2007-09-19 18:34:42.000000000 -0400
@@ -1,3 +1,17 @@
+mklibs (0.1.25) unstable; urgency=low
+
+  * New symbol versioning aware mklibs-readelf ported over from Waldi's
+    mklibs rewrite tree (r49384).
+  * Linking -usymbol@version only seems to work if there are multiple
+    versions of a symbol. Still pass -usymbol too, to get symbols that
+    have only one version. (See #443252 for detauls.)
+  * Add a hack to work around #443252; if a versioned symbol from slang or
+    newt cannot be resolved, check for an unversioned symbol and assume that
+    covers it.
+  * Closes: #433874
+
+ -- Joey Hess <joeyh@debian.org>  Wed, 19 Sep 2007 13:56:57 -0400
+
 mklibs (0.1.24) unstable; urgency=low
 
   * Also check for symboles without type. (closes: #433388)
diff -ur old/mklibs-0.1.24/debian/control mklibs-0.1.25/debian/control
--- old/mklibs-0.1.24/debian/control	2007-06-06 03:57:15.000000000 -0400
+++ mklibs-0.1.25/debian/control	2007-09-19 13:56:54.000000000 -0400
@@ -4,7 +4,7 @@
 Maintainer: Debian Install System Team <debian-boot@lists.debian.org>
 Build-Depends: debhelper (>= 4.2)
 Standards-Version: 3.6.1
-Uploaders: Phil Blundell <pb@debian.org>, Tollef Fog Heen <tfheen@debian.org>, Jeff Bailey <jbailey@nisa.net>, Bastian Blank <waldi@debian.org>, Frans Pop <fjp@debian.org>, Steve Langasek <vorlon@debian.org>
+Uploaders: Phil Blundell <pb@debian.org>, Tollef Fog Heen <tfheen@debian.org>, Jeff Bailey <jbailey@nisa.net>, Bastian Blank <waldi@debian.org>, Frans Pop <fjp@debian.org>, Steve Langasek <vorlon@debian.org>, Joey Hess <joeyh@debian.org>
 
 Package: mklibs
 Architecture: all
diff -ur old/mklibs-0.1.24/src/mklibs-readelf/elf.cpp mklibs-0.1.25/src/mklibs-readelf/elf.cpp
--- old/mklibs-0.1.24/src/mklibs-readelf/elf.cpp	2007-06-06 03:56:43.000000000 -0400
+++ mklibs-0.1.25/src/mklibs-readelf/elf.cpp	2007-09-19 15:09:35.000000000 -0400
@@ -18,53 +18,16 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#include "elf.hpp"
-#include "endian.hpp"
+#include "elf_data.hpp"
 
 #include <stdexcept>
 
 #include <fcntl.h>
-#include <elf.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 
 using namespace Elf;
 
-namespace
-{
-  template <typename _class>
-    struct _elfdef
-    { };
-
-  template <>
-    struct _elfdef<file_class_32>
-    {
-      typedef Elf32_Dyn Dyn;
-      typedef Elf32_Ehdr Ehdr;
-      typedef Elf32_Phdr Phdr;
-      typedef Elf32_Shdr Shdr;
-      typedef Elf32_Sym Sym;
-      static inline uint8_t st_bind (uint8_t st_info) throw () { return ELF32_ST_BIND (st_info); }
-      static inline uint8_t st_type (uint8_t st_info) throw () { return ELF32_ST_TYPE (st_info); }
-    };
-
-  template <>
-    struct _elfdef<file_class_64>
-    {
-      typedef Elf64_Dyn Dyn;
-      typedef Elf64_Ehdr Ehdr;
-      typedef Elf64_Phdr Phdr;
-      typedef Elf64_Shdr Shdr;
-      typedef Elf64_Sym Sym;
-      static inline uint8_t st_bind (uint8_t st_info) throw () { return ELF64_ST_BIND (st_info); }
-      static inline uint8_t st_type (uint8_t st_info) throw () { return ELF64_ST_TYPE (st_info); }
-    };
-}
-
-file::file (const char *filename, void *mem, size_t len) throw (std::bad_alloc)
-: filename (std::string (filename)), mem (mem), len (len)
-{ }
-
 file::~file () throw ()
 {
   ::munmap (mem, len);
@@ -93,9 +56,9 @@
     switch (buf[EI_CLASS])
     {
       case ELFCLASS32:
-        return open_class<file_class_32> (filename, buf, mem, len);
+        return open_class<file_class_32> (mem, len);
       case ELFCLASS64:
-        return open_class<file_class_64> (filename, buf, mem, len);
+        return open_class<file_class_64> (mem, len);
       default:
         throw std::runtime_error ("Invalid file class");
     }
@@ -108,35 +71,24 @@
 }
 
 template<typename _class>
-file *file::open_class (const char *filename, const uint8_t *buf, void * mem, size_t len) throw (std::bad_alloc, std::runtime_error)
+file *file::open_class (void * mem, size_t len) throw (std::bad_alloc, std::runtime_error)
 {
+  const uint8_t *buf = static_cast <uint8_t *> (mem);
+
   switch (buf[EI_DATA])
   {
     case ELFDATA2LSB:
-      return new file_data<_class, file_data_2LSB> (filename, mem, len);
+      return new file_data<_class, file_data_2LSB> (mem, len);
     case ELFDATA2MSB:
-      return new file_data<_class, file_data_2MSB> (filename, mem, len);
+      return new file_data<_class, file_data_2MSB> (mem, len);
     default:
       throw std::runtime_error ("Invalid file data");
   }
 }
 
 template <typename _class, typename _data>
-file_data<_class, _data>::file_data (const char *filename) throw (std::bad_alloc, std::runtime_error)
-: file (filename)
-{ 
-  construct ();
-}
-
-template <typename _class, typename _data>
-file_data<_class, _data>::file_data (const char *filename, void *mem, size_t len) throw (std::bad_alloc, std::runtime_error)
-: file (filename, mem, len)
-{
-  construct ();
-}
-
-template <typename _class, typename _data>
-void file_data<_class, _data>::construct () throw (std::bad_alloc, std::runtime_error)
+file_data<_class, _data>::file_data (void *mem, size_t len) throw (std::bad_alloc, std::runtime_error)
+: file (mem, len)
 {
   uint8_t *buf = static_cast <uint8_t *> (this->mem);
   if (buf[EI_CLASS] != _class::id)
@@ -167,11 +119,23 @@
     section *temp;
     switch (convert<_data, typeof (shdrs[i].sh_type)> () (shdrs[i].sh_type))
     {
+      case section_type_STRTAB::id:
+        temp = new section_real<_class, _data, section_type_STRTAB> (&shdrs[i], this->mem);
+        break;
       case section_type_DYNAMIC::id:
-        temp = new section_real<_class, _data, section_type_DYNAMIC> (&shdrs[i], this->mem);
+        temp = section_DYNAMIC = new section_real<_class, _data, section_type_DYNAMIC> (&shdrs[i], this->mem);
         break;
       case section_type_DYNSYM::id:
-        temp = new section_real<_class, _data, section_type_DYNSYM> (&shdrs[i], this->mem);
+        temp = section_DYNSYM = new section_real<_class, _data, section_type_DYNSYM> (&shdrs[i], this->mem);
+        break;
+      case section_type_GNU_VERDEF::id:
+        temp = section_GNU_VERDEF = new section_real<_class, _data, section_type_GNU_VERDEF> (&shdrs[i], this->mem);
+        break;
+      case section_type_GNU_VERNEED::id:
+        temp = section_GNU_VERNEED = new section_real<_class, _data, section_type_GNU_VERNEED> (&shdrs[i], this->mem);
+        break;
+      case section_type_GNU_VERSYM::id:
+        temp = section_GNU_VERSYM = new section_real<_class, _data, section_type_GNU_VERSYM> (&shdrs[i], this->mem);
         break;
       default:
         temp = new section_real<_class, _data, section_type_UNDEFINED> (&shdrs[i], this->mem);
@@ -191,7 +155,7 @@
     switch (convert<_data, typeof (phdrs[i].p_type)> () (phdrs[i].p_type))
     {
       case segment_type_INTERP::id:
-        temp = new segment_real<_class, _data, segment_type_INTERP> (&phdrs[i], this->mem);
+        temp = segment_INTERP = new segment_real<_class, _data, segment_type_INTERP> (&phdrs[i], this->mem);
         break;
       default:
         temp = new segment_real<_class, _data, segment_type_UNDEFINED> (&phdrs[i], this->mem);
@@ -201,13 +165,14 @@
   }
 
   for (unsigned int i = 0; i < this->shnum; i++)
-    this->sections[i]->update_string_table (this);
+    this->sections[i]->update (this);
 }
 
-void section::update_string_table (file *file) throw (std::bad_alloc)
+void section::update (const file *file) throw (std::bad_alloc)
 {
-  const section *section = file->get_section (file->get_shstrndx ());
-  this->name_string = std::string (static_cast <const char *> (section->_mem ()) + this->name);
+  const section_type<section_type_STRTAB> *section =
+    dynamic_cast <const section_type<section_type_STRTAB> *> (file->get_section (file->get_shstrndx ()));
+  this->name_string = section->get_string (this->name);
 }
 
 template <typename _class, typename _data>
@@ -245,11 +210,15 @@
     this->dynamics.push_back (new dynamic_data<_class, _data> (&dyns[i]));
 }
 
-void section_type<section_type_DYNAMIC>::update_string_table (file *file) throw (std::bad_alloc)
+void section_type<section_type_DYNAMIC>::update (const file *file) throw (std::bad_alloc)
 {
-  section::update_string_table (file);
+  section::update (file);
+
+  const section_type<section_type_STRTAB> *section =
+    dynamic_cast <const section_type<section_type_STRTAB> *> (file->get_section (link));
+
   for (unsigned int i = 0; i < dynamics.size (); i++)
-    this->dynamics[i]->update_string_table (file, link);
+    this->dynamics[i]->update_string (section);
 }
 
 section_type<section_type_DYNSYM>::~section_type () throw ()
@@ -258,11 +227,18 @@
     delete *it;
 }
 
-void section_type<section_type_DYNSYM>::update_string_table (file *file) throw (std::bad_alloc)
+void section_type<section_type_DYNSYM>::update (const file *file) throw (std::bad_alloc)
 {
-  section::update_string_table (file);
+  section::update (file);
+
+  const section_type<section_type_STRTAB> *section =
+    dynamic_cast <const section_type<section_type_STRTAB> *> (file->get_section (link));
+
   for (unsigned int i = 0; i < symbols.size (); i++)
-    this->symbols[i]->update_string_table (file, link);
+  {
+    symbols[i]->update_string (section);
+    symbols[i]->update_version (file, i);
+  }
 }
 
 template <typename _class, typename _data>
@@ -281,6 +257,105 @@
     this->symbols.push_back (new symbol_data<_class, _data> (&syms[i]));
 }
 
+const version_definition *section_type<section_type_GNU_VERDEF>::get_version_definition(uint16_t index) const throw ()
+{
+  for (std::vector<version_definition *>::const_iterator it = verdefs.begin(); it != verdefs.end(); ++it)
+    if ((*it)->get_ndx() == index)
+      return *it;
+  return NULL;
+}
+
+void section_type<section_type_GNU_VERDEF>::update (const file *file) throw (std::bad_alloc)
+{
+  section::update (file);
+
+  const section_type<section_type_STRTAB> *section =
+    dynamic_cast <const section_type<section_type_STRTAB> *> (file->get_section (link));
+
+  for (std::vector<version_definition *>::iterator it = verdefs.begin (); it != verdefs.end (); ++it)
+    (*it)->update_string (section);
+}
+
+template <typename _class, typename _data>
+section_real<_class, _data, section_type_GNU_VERDEF>::section_real (void *header, void *mem) throw (std::bad_alloc)
+: section_data<_class, _data> (header, mem)
+{
+  if (this->type != SHT_GNU_verdef)
+    throw std::logic_error ("Wrong section type");
+
+  typedef typename _elfdef<_class>::Verdef Verdef;
+  char *act = static_cast<char *> (this->mem);
+  uint32_t next = 0;
+
+  // TODO: Use DT_VERDEFNUM!
+  do
+  {
+    Verdef *verdef = reinterpret_cast<Verdef *> (act);
+    verdefs.push_back(new version_definition_data<_class, _data> (verdef));
+    next = convert<_data, typeof (verdef->vd_next)> () (verdef->vd_next);
+    act += next;
+  }
+  while (next);
+}
+
+const version_requirement_entry *section_type<section_type_GNU_VERNEED>::get_version_requirement_entry(uint16_t index) const throw ()
+{
+  for (std::vector<version_requirement *>::const_iterator it = verneeds.begin(); it != verneeds.end(); ++it)
+    for (std::vector<version_requirement_entry *>::const_iterator it1 = (*it)->get_entries().begin(); it1 != (*it)->get_entries().end(); ++it1)
+      if ((*it1)->get_other() == index)
+        return *it1;
+  return NULL;
+}
+
+void section_type<section_type_GNU_VERNEED>::update (const file *file) throw (std::bad_alloc)
+{
+  section::update (file);
+
+  const section_type<section_type_STRTAB> *section =
+    dynamic_cast <const section_type<section_type_STRTAB> *> (file->get_section (link));
+
+  for (std::vector<version_requirement *>::iterator it = verneeds.begin (); it != verneeds.end (); ++it)
+    (*it)->update_string (section);
+}
+
+template <typename _class, typename _data>
+section_real<_class, _data, section_type_GNU_VERNEED>::section_real (void *header, void *mem) throw (std::bad_alloc)
+: section_data<_class, _data> (header, mem)
+{
+  if (this->type != SHT_GNU_verneed)
+    throw std::logic_error ("Wrong section type");
+
+  typedef typename _elfdef<_class>::Verneed Verneed;
+  char *act = static_cast<char *> (this->mem);
+  uint32_t next = 0;
+
+  // TODO: Use DT_VERNEEDNUM!
+  do
+  {
+    Verneed *verneed = reinterpret_cast<Verneed *> (act);
+    verneeds.push_back(new version_requirement_data<_class, _data> (verneed));
+    next = convert<_data, typeof (verneed->vn_next)> () (verneed->vn_next);
+    act += next;
+  }
+  while (next);
+}
+
+template <typename _class, typename _data>
+section_real<_class, _data, section_type_GNU_VERSYM>::section_real (void *header, void *mem) throw (std::bad_alloc)
+: section_data<_class, _data> (header, mem)
+{
+  if (this->type != SHT_GNU_versym)
+    throw std::logic_error ("Wrong section type");
+  typedef typename _elfdef<_class>::Versym Versym;
+  Versym *versyms = static_cast <Versym *> (this->mem);
+  unsigned int max = this->size / sizeof (Versym);
+
+  this->versyms.reserve (max);
+
+  for (unsigned int i = 0; i < max; i++)
+    this->versyms.push_back (versyms[i]);
+}
+
 template <typename _class, typename _data>
 segment_data<_class, _data>::segment_data (void *header, void *mem) throw ()
 {
@@ -325,11 +400,32 @@
 }
 
 template <typename _class, typename _data>
-void dynamic_data<_class, _data>::update_string_table (file *file, uint16_t s) throw (std::bad_alloc)
+void dynamic_data<_class, _data>::update_string (const section_type<section_type_STRTAB> *section) throw (std::bad_alloc)
 {
-  const section *section = file->get_section (s);
   if (this->is_string)
-    this->val_string = std::string (static_cast <const char *> (section->_mem ()) + this->val);
+    this->val_string = section->get_string (this->val);
+}
+
+std::string symbol::get_version () const throw (std::bad_alloc)
+{
+  if (verneed)
+    return verneed->get_name();
+  else if (verdef)
+    return verdef->get_names()[0];
+
+  return version;
+}
+
+std::string symbol::get_name_version () const throw (std::bad_alloc)
+{
+  std::string ver;
+
+  if (verneed)
+    ver = '@' + verneed->get_name();
+  else if (verdef)
+    ver = '@' + verdef->get_names()[0];
+
+  return name_string + ver;
 }
 
 template <typename _class, typename _data>
@@ -347,9 +443,99 @@
 }
 
 template <typename _class, typename _data>
-void symbol_data<_class, _data>::update_string_table (file *file, uint16_t s) throw (std::bad_alloc)
+void symbol_data<_class, _data>::update_string (const section_type<section_type_STRTAB> *section) throw (std::bad_alloc)
+{
+  this->name_string = section->get_string (this->name);
+}
+
+template <typename _class, typename _data>
+void symbol_data<_class, _data>::update_version(const file *file, uint16_t index) throw (std::bad_alloc)
+{
+  if (!file->get_section_GNU_VERSYM())
+    return;
+
+  uint16_t versym = file->get_section_GNU_VERSYM()->get_versyms().at(index);
+
+  if (versym == 0)
+    version = "*Base*";
+  else if (versym == 1)
+    version = "*global*";
+  else
+  {
+    if (file->get_section_GNU_VERNEED())
+      verneed = file->get_section_GNU_VERNEED()->get_version_requirement_entry(versym);
+
+    if (!verneed)
+    {
+      if (file->get_section_GNU_VERDEF())
+        verdef = file->get_section_GNU_VERDEF()->get_version_definition(versym & 0x7fff);
+      if (!verdef)
+        throw std::runtime_error("Invalid version");
+    }
+  }
+}
+
+template <typename _class, typename _data>
+version_definition_data<_class, _data>::version_definition_data (Verdef *verdef) throw ()
+{
+  this->ndx    = convert<_data, typeof (verdef->vd_ndx)> () (verdef->vd_ndx);
+  uint16_t cnt = convert<_data, typeof (verdef->vd_cnt)> () (verdef->vd_cnt);
+  uint32_t aux = convert<_data, typeof (verdef->vd_aux)> () (verdef->vd_aux);
+
+  char *act = reinterpret_cast<char *> (verdef) + aux;
+
+  for (int i = 0; i < cnt; i++)
+  {
+    Verdaux *verdaux = reinterpret_cast<Verdaux *> (act);
+    uint32_t name = convert<_data, typeof (verdaux->vda_name)> () (verdaux->vda_name);
+    uint32_t next = convert<_data, typeof (verdaux->vda_next)> () (verdaux->vda_next);
+    names.push_back(name);
+    act += next;
+  }
+}
+
+template <typename _class, typename _data>
+void version_definition_data<_class, _data>::update_string (const section_type<section_type_STRTAB> *section) throw (std::bad_alloc)
+{
+  for (std::vector<uint32_t>::iterator it = names.begin (); it != names.end (); ++it)
+    names_string.push_back (section->get_string (*it));
+}
+
+template <typename _class, typename _data>
+version_requirement_data<_class, _data>::version_requirement_data (Verneed *verneed) throw ()
+{
+  uint16_t cnt = convert<_data, typeof (verneed->vn_cnt)> () (verneed->vn_cnt);
+  uint32_t aux = convert<_data, typeof (verneed->vn_aux)> () (verneed->vn_aux);
+
+  char *act = reinterpret_cast<char *> (verneed) + aux;
+
+  for (int i = 0; i < cnt; i++)
+  {
+    Vernaux *vernaux = reinterpret_cast<Vernaux *> (act);
+    entries.push_back(new version_requirement_entry_data<_class, _data> (vernaux));
+    uint32_t next = convert<_data, typeof (vernaux->vna_next)> () (vernaux->vna_next);
+    act += next;
+  }
+}
+
+template <typename _class, typename _data>
+void version_requirement_data<_class, _data>::update_string (const section_type<section_type_STRTAB> *section) throw (std::bad_alloc)
+{
+  for (std::vector<version_requirement_entry *>::iterator it = entries.begin (); it != entries.end (); ++it)
+    (*it)->update_string (section);
+}
+
+template <typename _class, typename _data>
+version_requirement_entry_data<_class, _data>::version_requirement_entry_data (Vernaux *vna) throw ()
+{
+  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);
+}
+
+template <typename _class, typename _data>
+void version_requirement_entry_data<_class, _data>::update_string (const section_type<section_type_STRTAB> *section) throw (std::bad_alloc)
 {
-  const section *section = file->get_section (s);
-  this->name_string = std::string (static_cast <const char *> (section->_mem ()) + this->name);
+  name_string = section->get_string (name);
 }
 
diff -ur old/mklibs-0.1.24/src/mklibs-readelf/elf.hpp mklibs-0.1.25/src/mklibs-readelf/elf.hpp
--- old/mklibs-0.1.24/src/mklibs-readelf/elf.hpp	2007-06-06 03:56:43.000000000 -0400
+++ mklibs-0.1.25/src/mklibs-readelf/elf.hpp	2007-09-19 13:51:56.000000000 -0400
@@ -21,7 +21,7 @@
 #ifndef ELF_HPP
 #define ELF_HPP
 
-#include "endian.hpp"
+#include "elf_defs.hpp"
 
 #include <stdexcept>
 #include <string>
@@ -31,18 +31,10 @@
 
 namespace Elf
 {
-  class file_class_32 { public: static const uint8_t id = 1; };
-  class file_class_64 { public: static const uint8_t id = 2; };
-  class file_data_2LSB { public: static const uint8_t id = 1; };
-  class file_data_2MSB { public: static const uint8_t id = 2; };
-  class section_type_UNDEFINED { };
-  class section_type_DYNAMIC { public: static const uint8_t id = 6; };
-  class section_type_DYNSYM { public: static const uint8_t id = 11; };
-  class segment_type_UNDEFINED { };
-  class segment_type_INTERP { public: static const uint8_t id = 3; };
-
   class section;
+  template <typename _type> class section_type;
   class segment;
+  template <typename _type> class segment_type;
 
   class file
   {
@@ -58,17 +50,22 @@
 
       const std::vector <section *> get_sections () const throw () { return sections; };
       const section *get_section (unsigned int i) const throw (std::out_of_range) { return sections.at(i); };
-      const std::vector <segment *> get_segments () const throw () { return segments; };
+      const section_type<section_type_DYNAMIC> *get_section_DYNAMIC () const throw () { return section_DYNAMIC; };
+      const section_type<section_type_DYNSYM> *get_section_DYNSYM () const throw () { return section_DYNSYM; };
+      const section_type<section_type_GNU_VERDEF> *get_section_GNU_VERDEF () const throw () { return section_GNU_VERDEF; };
+      const section_type<section_type_GNU_VERNEED> *get_section_GNU_VERNEED () const throw () { return section_GNU_VERNEED; };
+      const section_type<section_type_GNU_VERSYM> *get_section_GNU_VERSYM () const throw () { return section_GNU_VERSYM; };
 
-      const void *const _mem () const throw () { return mem; }
+      const std::vector <segment *> get_segments () const throw () { return segments; };
+      const segment_type<segment_type_INTERP> *get_segment_INTERP () const throw () { return segment_INTERP; };
 
       static file *open (const char *filename) throw (std::bad_alloc, std::runtime_error);
 
     protected:
-      file (const char *, void *, size_t len) throw (std::bad_alloc);
+      file (void *mem, size_t len) throw (std::bad_alloc) : mem (mem), len (len) { }
 
       template<typename _class>
-        static file *open_class (const char *, const uint8_t *, void *, size_t) throw (std::bad_alloc, std::runtime_error);
+        static file *open_class (void *, size_t) throw (std::bad_alloc, std::runtime_error);
 
       uint16_t type;
       uint16_t machine;
@@ -82,27 +79,19 @@
       uint16_t shstrndx;
 
       std::vector <section *> sections;
+      section_type<section_type_DYNAMIC> *section_DYNAMIC;
+      section_type<section_type_DYNSYM> *section_DYNSYM;
+      section_type<section_type_GNU_VERDEF> *section_GNU_VERDEF;
+      section_type<section_type_GNU_VERNEED> *section_GNU_VERNEED;
+      section_type<section_type_GNU_VERSYM> *section_GNU_VERSYM;
+
       std::vector <segment *> segments;
+      segment_type<segment_type_INTERP> *segment_INTERP;
 
-      const std::string filename;
       void *mem;
       size_t len;
   };
 
-  template <typename _class, typename _data>
-    class file_data : public file
-    {
-      public:
-        file_data (const char *) throw (std::bad_alloc, std::runtime_error);
-        file_data (const char *, void *, size_t len) throw (std::bad_alloc, std::runtime_error);
-
-        const uint8_t get_class () const throw () { return _class::id; }
-        const uint8_t get_data () const throw () { return _data::id; }
-
-      private:
-        void construct () throw (std::bad_alloc, std::runtime_error);
-    };
-
   class section
   {
     public:
@@ -112,9 +101,7 @@
       uint64_t get_size () const throw () { return size; }
       const std::string &get_name_string () const throw () { return name_string; }
 
-      const void *const _mem () const throw () { return mem; }
-
-      virtual void update_string_table (file *) throw (std::bad_alloc);
+      virtual void update (const file *) throw (std::bad_alloc);
 
     protected:
       uint32_t name;
@@ -128,13 +115,6 @@
       void *mem;
   };
 
-  template <typename _class, typename _data>
-    class section_data : public virtual section
-    {
-      public:
-        section_data (void *, void *) throw ();
-    };
-
   template <typename _type>
     class section_type : public virtual section
     {
@@ -142,6 +122,19 @@
 
   class dynamic;
   class symbol;
+  class version_definition;
+  class version_requirement;
+  class version_requirement_entry;
+
+  template <>
+    class section_type<section_type_STRTAB> : public virtual section
+    {
+      public:
+        std::string get_string (uint32_t offset) const throw (std::bad_alloc)
+        {
+          return std::string (static_cast<const char *> (mem) + offset);
+        }
+    };
 
   template <>
     class section_type<section_type_DYNAMIC> : public virtual section
@@ -149,9 +142,9 @@
       public:
         ~section_type () throw ();
 
-        const std::vector<dynamic *> &get_dynamics () throw () { return dynamics; }
+        const std::vector<dynamic *> &get_dynamics () const throw () { return dynamics; }
 
-        void update_string_table (file *) throw (std::bad_alloc);
+        void update (const file *) throw (std::bad_alloc);
 
       protected:
         std::vector<dynamic *> dynamics;
@@ -163,40 +156,54 @@
       public:
         ~section_type () throw ();
 
-        const std::vector<symbol *> &get_symbols () throw () { return symbols; }
+        const std::vector<symbol *> &get_symbols () const throw () { return symbols; }
 
-        void update_string_table (file *) throw (std::bad_alloc);
+        void update (const file *) throw (std::bad_alloc);
 
       protected:
         std::vector<symbol *> symbols;
     };
 
-  template <typename _class, typename _data, typename _type>
-    class section_real : public section_data<_class, _data>, public section_type<_type>
+  template <>
+    class section_type<section_type_GNU_VERDEF> : public virtual section
     {
       public:
-        section_real (void *, void *) throw ();
-    };
+        ~section_type () throw () { }
 
-  template <typename _class, typename _data>
-    class section_real<_class, _data, section_type_UNDEFINED> : public section_data<_class, _data>, public section_type<section_type_UNDEFINED>
-    {
-      public:
-        section_real (void *a, void *b) throw () : section_data<_class, _data> (a, b) { }
+        const version_definition *get_version_definition(uint16_t index) const throw ();
+        const std::vector<version_definition *> &get_version_definitions () throw () { return verdefs; }
+
+        void update (const file *) throw (std::bad_alloc);
+
+      protected:
+        std::vector<version_definition *> verdefs;
     };
 
-  template <typename _class, typename _data>
-    class section_real<_class, _data, section_type_DYNAMIC> : public section_data<_class, _data>, public section_type<section_type_DYNAMIC>
+  template <>
+    class section_type<section_type_GNU_VERNEED> : public virtual section
     {
       public:
-        section_real (void *, void *) throw (std::bad_alloc);
+        ~section_type () throw () { }
+
+        const version_requirement_entry *get_version_requirement_entry(uint16_t index) const throw ();
+        const std::vector<version_requirement *> &get_version_requirements () throw () { return verneeds; }
+
+        void update (const file *) throw (std::bad_alloc);
+
+      protected:
+        std::vector<version_requirement *> verneeds;
     };
 
-  template <typename _class, typename _data>
-    class section_real<_class, _data, section_type_DYNSYM> : public section_data<_class, _data>, public section_type<section_type_DYNSYM>
+  template <>
+    class section_type<section_type_GNU_VERSYM> : public virtual section
     {
       public:
-        section_real (void *, void *) throw (std::bad_alloc);
+        ~section_type () throw () { }
+
+        const std::vector<uint16_t> &get_versyms () const throw () { return versyms; }
+
+      protected:
+        std::vector<uint16_t> versyms;
     };
 
   class segment
@@ -208,8 +215,6 @@
       uint32_t get_flags () const throw () { return flags; }
       uint64_t get_filesz () const throw () { return filesz; }
 
-      const void *const _mem () const throw () { return mem; }
-
     protected:
       uint32_t type;
       uint32_t flags;
@@ -219,13 +224,6 @@
       void *mem;
   };
 
-  template <typename _class, typename _data>
-    class segment_data : public virtual segment
-    {
-      public:
-        segment_data (void *, void *) throw ();
-    };
-
   template <typename _type>
     class segment_type : public virtual segment
     {
@@ -243,29 +241,6 @@
         std::string interp;
     };
 
-  template <typename _class, typename _data, typename _type>
-    class segment_real : public segment_data<_class, _data>, public segment_type<_type>
-    {
-      public:
-        segment_real (void *, void *) throw ();
-    };
-
-  template <typename _class, typename _data>
-    class segment_real<_class, _data, segment_type_UNDEFINED>
-    : public segment_data<_class, _data>, public segment_type<segment_type_UNDEFINED>
-    {
-      public:
-        segment_real (void *a, void *b) throw () : segment_data<_class, _data> (a, b) { }
-    };
-
-  template <typename _class, typename _data>
-    class segment_real<_class, _data, segment_type_INTERP>
-    : public segment_data<_class, _data>, public segment_type<segment_type_INTERP>
-    {
-      public:
-        segment_real (void *, void *) throw (std::bad_alloc);
-    };
-
   class dynamic
   {
     public:
@@ -276,7 +251,7 @@
       uint64_t get_ptr () const throw () { return ptr; }
       const std::string &get_val_string () const throw () { return val_string; }
 
-      virtual void update_string_table (file *, uint16_t) throw (std::bad_alloc) = 0;
+      virtual void update_string (const section_type<section_type_STRTAB> *) throw (std::bad_alloc) = 0;
 
     protected:
       int64_t tag;
@@ -287,19 +262,11 @@
       std::string val_string;
   };
 
-  template <typename _class, typename _data>
-    class dynamic_data : public dynamic
-    {
-      public:
-        dynamic_data (void *) throw ();
-
-        void update_string_table (file *, uint16_t) throw (std::bad_alloc);
-    };
-
   class symbol
   {
     public:
-      virtual ~symbol () throw () {}
+      symbol() throw () : verdef(NULL), verneed(NULL) {}
+      virtual ~symbol() throw () {}
 
       uint8_t get_info () const throw () { return info; }
       uint16_t get_shndx () const throw () { return shndx; }
@@ -308,8 +275,11 @@
       uint8_t get_bind () const throw () { return bind; }
       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_name_version() const throw (std::bad_alloc);
 
-      virtual void update_string_table (file *, uint16_t) throw (std::bad_alloc) = 0;
+      virtual void update_string (const section_type<section_type_STRTAB> *) throw (std::bad_alloc) = 0;
+      virtual void update_version (const file *, uint16_t) throw (std::bad_alloc) = 0;
 
     protected:
       uint32_t name;
@@ -321,28 +291,61 @@
       uint8_t type;
 
       std::string name_string;
+      std::string version;
+      const version_definition *verdef;
+      const version_requirement_entry *verneed;
   };
 
-  template <typename _class, typename _data>
-    class symbol_data : public symbol
-    {
-      public:
-        symbol_data (void *) throw ();
+  class version_definition
+  {
+    public:
+      virtual ~version_definition() throw () { }
 
-        void update_string_table (file *, uint16_t) throw (std::bad_alloc);
-    };
+      uint16_t get_ndx() const throw () { return ndx; }
+      const std::vector<std::string> &get_names() const throw () { return names_string; }
+
+      virtual void update_string(const section_type<section_type_STRTAB> *) throw (std::bad_alloc) = 0;
+
+    protected:
+      uint16_t ndx;
 
-  template <typename from, typename type>
-    struct convert
-    { };
-
-  template <typename type>
-    struct convert<file_data_2LSB, type> : public endian::convert<endian::little_endian, type>
-    { };
-
-  template <typename type>
-    struct convert<file_data_2MSB, type> : public endian::convert<endian::big_endian, type>
-    { };
+      std::vector<uint32_t> names;
+
+      std::vector<std::string> names_string;
+  };
+
+  class version_requirement_entry;
+
+  class version_requirement
+  {
+    public:
+      virtual ~version_requirement () throw () { }
+
+      const std::vector<version_requirement_entry *> &get_entries () const throw () { return entries; }
+
+      virtual void update_string (const section_type<section_type_STRTAB> *) throw (std::bad_alloc) = 0;
+
+    protected:
+      std::vector<version_requirement_entry *> entries;
+  };
+
+  class version_requirement_entry
+  {
+    public:
+      virtual ~version_requirement_entry () throw () { }
+
+      uint16_t get_other () const throw () { return other; }
+      const std::string &get_name() const throw () { return name_string; }
+
+      virtual void update_string (const section_type<section_type_STRTAB> *) throw (std::bad_alloc) = 0;
+
+    protected:
+      uint16_t flags;
+      uint16_t other;
+      uint32_t name;
+
+      std::string name_string;
+  };
 }
 
 #endif
Only in mklibs-0.1.25/src/mklibs-readelf: elf_data.hpp
Only in mklibs-0.1.25/src/mklibs-readelf: elf_defs.hpp
Only in mklibs-0.1.25/src/mklibs-readelf: elf_endian.hpp
diff -ur old/mklibs-0.1.24/src/mklibs-readelf/main.cpp mklibs-0.1.25/src/mklibs-readelf/main.cpp
--- old/mklibs-0.1.24/src/mklibs-readelf/main.cpp	2007-07-16 17:00:54.000000000 -0400
+++ mklibs-0.1.25/src/mklibs-readelf/main.cpp	2007-09-19 16:35:35.000000000 -0400
@@ -52,8 +52,9 @@
     << file->get_flags () << '\n';
 }
 
-static void process_dynamics (Elf::section_type<Elf::section_type_DYNAMIC> *section, int64_t tag)
+static void process_dynamics (Elf::file *file, int64_t tag)
 {
+  const Elf::section_type<Elf::section_type_DYNAMIC> *section = file->get_section_DYNAMIC ();
   for (std::vector<Elf::dynamic *>::const_iterator it = section->get_dynamics ().begin (); it != section->get_dynamics ().end (); ++it)
   {
     Elf::dynamic *dynamic = *it;
@@ -62,7 +63,7 @@
   }
 }
 
-static void process_symbols_provided (Elf::section_type<Elf::section_type_DYNSYM> *section)
+static void process_symbols_provided (const Elf::section_type<Elf::section_type_DYNSYM> *section)
 {
   for (std::vector<Elf::symbol *>::const_iterator it = section->get_symbols ().begin (); it != section->get_symbols ().end (); ++it)
   {
@@ -73,49 +74,38 @@
     if (shndx == SHN_UNDEF || shndx == SHN_ABS)
       continue;
     if (type == STT_NOTYPE || type == STT_OBJECT || type == STT_FUNC || type == STT_COMMON || type == STT_TLS)
-      std::cout << symbol->get_name_string () << ' ' << (bind == STB_WEAK ? "True" : "False") << '\n';
+      std::cout <<
+//        symbol->get_name_string () << ' ' <<
+//        symbol->get_version() << ' ' <<
+        symbol->get_name_version() << ' ' <<
+        (bind == STB_WEAK ? "True" : "False") << '\n';
+//        symbol->get_name_string () << ' ' <<
+//        (bind == STB_WEAK ? "True" : "False") << '\n';
   }
 }
 
-static void process_symbols_undefined (Elf::section_type<Elf::section_type_DYNSYM> *section)
+static void process_symbols_undefined (const Elf::section_type<Elf::section_type_DYNSYM> *section)
 {
   for (std::vector<Elf::symbol *>::const_iterator it = section->get_symbols ().begin (); it != section->get_symbols ().end (); ++it)
   {
     const Elf::symbol *symbol = *it;
     uint8_t bind = symbol->get_bind ();
     uint16_t shndx = symbol->get_shndx ();
-    uint8_t type = symbol->get_type ();
     if (shndx != SHN_UNDEF)
       continue;
     if (bind == STB_GLOBAL || bind == STB_WEAK)
-      std::cout << symbol->get_name_string () << ' ' << (bind == STB_WEAK ? "True" : "False") << '\n';
+      std::cout <<
+//        symbol->get_version() << ' ' <<
+        symbol->get_name_version() << ' ' <<
+        (bind == STB_WEAK ? "True" : "False") << '\n';
+//        symbol->get_name_string () << ' ' <<
+//        (bind == STB_WEAK ? "True" : "False") << '\n';
   }
 }
 
 static void process (command cmd, const char *filename)
 {
   Elf::file *file = Elf::file::open (filename);
-  const std::vector <Elf::section *> &sections = file->get_sections ();
-  const std::vector <Elf::segment *> &segments = file->get_segments ();
-  Elf::section_type<Elf::section_type_DYNAMIC> *section_dynamic = 0;
-  Elf::section_type<Elf::section_type_DYNSYM> *section_dynsym = 0;
-  Elf::segment_type<Elf::segment_type_INTERP> *segment_interp = 0;
-
-  for (std::vector <Elf::section *>::const_iterator it = sections.begin (); it != sections.end (); ++it)
-  {
-    uint32_t type = (*it)->get_type ();
-    if (type == Elf::section_type_DYNAMIC::id)
-      section_dynamic = dynamic_cast <Elf::section_type<Elf::section_type_DYNAMIC> *> (*it);
-    else if (type == Elf::section_type_DYNSYM::id)
-      section_dynsym = dynamic_cast <Elf::section_type<Elf::section_type_DYNSYM> *> (*it);
-  }
-
-  for (std::vector <Elf::segment *>::const_iterator it = segments.begin (); it != segments.end (); ++it)
-  {
-    uint32_t type = (*it)->get_type ();
-    if (type == Elf::segment_type_INTERP::id)
-      segment_interp = dynamic_cast <Elf::segment_type<Elf::segment_type_INTERP> *> (*it);
-  }
 
   switch (cmd)
   {
@@ -123,23 +113,23 @@
       process_elf_header (file);
       break;
     case COMMAND_PRINT_INTERP:
-      if (segment_interp)
-        std::cout << segment_interp->get_interp () << '\n';
+      if (file->get_segment_INTERP ())
+        std::cout << file->get_segment_INTERP ()->get_interp () << '\n';
       break;
     case COMMAND_PRINT_NEEDED:
-      process_dynamics (section_dynamic, DT_NEEDED);
+      process_dynamics (file, DT_NEEDED);
       break;
     case COMMAND_PRINT_RPATH:
-      process_dynamics (section_dynamic, DT_RPATH);
+      process_dynamics (file, DT_RPATH);
       break;
     case COMMAND_PRINT_SONAME:
-      process_dynamics (section_dynamic, DT_SONAME);
+      process_dynamics (file, DT_SONAME);
       break;
     case COMMAND_PRINT_SYMBOLS_PROVIDED:
-      process_symbols_provided (section_dynsym);
+      process_symbols_provided (file->get_section_DYNSYM ());
       break;
     case COMMAND_PRINT_SYMBOLS_UNDEFINED:
-      process_symbols_undefined (section_dynsym);
+      process_symbols_undefined (file->get_section_DYNSYM ());
       break;
   }
 }
diff -ur old/mklibs-0.1.24/src/mklibs.py mklibs-0.1.25/src/mklibs.py
--- old/mklibs-0.1.24/src/mklibs.py	2007-06-11 03:58:05.000000000 -0400
+++ mklibs-0.1.25/src/mklibs.py	2007-09-19 18:47:47.000000000 -0400
@@ -397,8 +397,13 @@
     if unresolved == previous_pass_unresolved:
         # No progress in last pass. Verify all remaining symbols are weak.
         for (symbol, is_weak) in unresolved:
-            if not is_weak:
-                raise "Unresolvable symbol " + symbol
+	    if not is_weak:
+	    	# XXX horrible workaround for #443252
+	        if symbol_versions[re.sub("@.*", "", symbol)] == 1:
+		    debug(DEBUG_VERBOSE, "Ignoring potentially unresolvable",
+			symbol, "since there is exactly one version")
+		else:
+                    raise "Unresolvable symbol " + symbol
         break
 
     previous_pass_unresolved = unresolved
@@ -406,6 +411,7 @@
     library_symbols = {}
     library_symbols_used = {}
     symbol_provider = {}
+    symbol_versions = {}
 
     # WORKAROUND: Always add libgcc on old-abi arm
     header = elf_header(find_lib(libraries.copy().pop()))
@@ -433,6 +440,12 @@
             else:
                 library_symbols[library].add(symbol)
                 symbol_provider[symbol] = library
+	    
+	    symbol_base=re.sub("@.*", "", symbol)
+	    if symbol_versions.has_key(symbol_base):
+	    	symbol_versions[symbol_base]=symbol_versions[symbol_base]+1
+	    else:
+		symbol_versions[symbol_base]=1
 
     # which symbols are actually used from each lib
     for (symbol, is_weak) in needed_symbols:
@@ -495,6 +508,8 @@
             cmd = []
             cmd.append("-nostdlib -nostartfiles -shared -Wl,-soname=" + soname)
             cmd.extend(["-u%s" % a for a in symbols])
+	    # XXX workaround for #443252
+            cmd.extend(["-u%s" % re.sub("@.*", "", a) for a in symbols])
             cmd.extend(["-o", dest_path + "/" + so_file_name + "-so"])
             cmd.extend(extra_pre_obj)
             cmd.append(pic_file)

Attachment: signature.asc
Description: Digital signature


Reply to: