Frans Pop wrote:
I've just given your patch a try, but if I try to build the Debian
Installer (which in Debian is the main user of mklibs) with it on a
system running Debian/unstable amd64, I get the following error:
Sorry for the delay, I've been busy.
Please try the attached updated patch. I've added a fall back for
@unknown symbols. This is basically the same as the previous
implementation - it just selects the first instance of each symbol. I
believe this should match the behaviour of the dynamic linker.
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 | 38 +++++++++++++++++++++++---------------
5 files changed, 51 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> §ion) 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" % (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" % (self.name, self.version), "%...@base" % self.name]
+ ver, lib = self.version.split('@', 1)[:2]
+ if self.default_version and ver != "Base":
+ return ["%...@%s" % (self.name, self.version), "%...@base@%s" % (self.name, lib)]
return ["%...@%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" % (self.name, self.version)
+ return "%...@%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" % (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,14 @@ 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 = "%...@unknown" % name.rsplit('@', 1)[0]
+ if not nolib_name in symbol_provider:
+ symbol_provider[nolib_name] = library
# which symbols are actually used from each lib
for name in needed_symbols:
@@ -540,7 +548,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', 'b...@%s' % soname, True))
map_file = find_pic_map(library)
if map_file: