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: 'strlong...@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> §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,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 = "%...@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', 'b...@%s' % soname, True)) map_file = find_pic_map(library) if map_file: