Bug#172828: mklib: weak symbols patch
Alastair McKinstry <mckinstry@computer.org> writes:
> A while ago you said you would try to do a weak-symbols patch for
> mklibs; this is needed for mips to work on debian-installer.
Here's a patch, I have not really tested it yet. Maybe you can give it
a try?
--
Falk
Index: mklibs.py
===================================================================
RCS file: /cvs/debian-boot/mklibs/mklibs.py,v
retrieving revision 1.21
diff -u -p -r1.21 mklibs.py
--- mklibs.py 7 May 2003 20:02:22 -0000 1.21
+++ mklibs.py 11 May 2003 17:04:22 -0000
@@ -59,7 +59,8 @@ def debug(level, *msg):
if debuglevel >= level:
print string.join(msg)
-# A simple set class.
+# A simple set class. It should be replaced with the standard sets.Set
+# type as soon as Python 2.3 is out.
class Set:
def __init__(self):
self.__dict = {}
@@ -80,6 +81,9 @@ class Set:
def size(self):
return len(self.__dict)
+ def __eq__(self, other):
+ return self.__dict == other.__dict
+
def __str__(self):
return `self.__dict.keys()`
@@ -132,28 +136,41 @@ def library_depends_gcc_libnames(obj):
else:
return "-l" + string.join(output.elems(), " -l")
-# Return a Set of undefined symbols in an object
+# scan readelf output. Example:
+# Num: Value Size Type Bind Vis Ndx Name
+# 1: 000000012002ab48 168 FUNC GLOBAL DEFAULT UND strchr@GLIBC_2.0 (2)
+symline_regexp = \
+ re.compile("\s*\d+: .+\s+\d+\s+\w+\s+(\w+)+\s+\w+\s+(\w+)\s+(\w+)")
+
+# Return undefined symbols in an object as a Set of tuples (name, weakness)
def undefined_symbols(obj):
if not os.access(obj, os.F_OK):
raise "Cannot find lib" + obj
+
+ result = Set()
output = command(target + "readelf", "-s", "-W", obj)
- output = filter(lambda x: string.find(x, "NOTYPE") == -1, output)
- output = filter(lambda x: string.find(x, "SECTION") == -1, output)
- output = filter(lambda x: string.find(x, "ABS") == -1, output)
- output = filter(lambda x: string.find(x, "LOCAL") == -1, output)
- return regexpfilter(output, ".*\sUND\s([^@\s]+)(@.+)?$")
+ for line in output:
+ match = symline_regexp.match(line)
+ if match:
+ bind, ndx, name = match.groups()
+ if ndx == "UND":
+ result.add((name, bind == "WEAK"))
+ return result
# Return a Set of symbols provided by a library
def provided_symbols(obj):
if not os.access(obj, os.F_OK):
raise "Cannot find lib" + obj
+
+ result = Set()
output = command(target + "readelf", "-s", "-W", obj)
- output = filter(lambda x: string.find(x, "UND") == -1, output)
- output = filter(lambda x: string.find(x, "NOTYPE") == -1, output)
- output = filter(lambda x: string.find(x, "SECTION") == -1, output)
- output = filter(lambda x: string.find(x, "ABS") == -1, output)
- output = filter(lambda x: string.find(x, " LOCAL ") == -1, output)
- return regexpfilter(output, ".*\d+:\s[\da-fA-f]+\s.+\s\d+\s([^@]+)(@\S+)?$")
+ for line in output:
+ match = symline_regexp.match(line)
+ if match:
+ bind, ndx, name = match.groups()
+ if bind != "LOCAL" and not ndx in ("UND", "ABS"):
+ result.add(name)
+ return result
# Return real target of a symlink
def resolve_link(file):
@@ -326,6 +343,7 @@ for obj in objects.values():
lib_path.extend(lib_rpath)
passnr = 1
+previous_pass_unresolved = Set()
while 1:
debug(DEBUG_NORMAL, "I: library reduction pass", `passnr`)
if debuglevel >= DEBUG_VERBOSE:
@@ -352,7 +370,7 @@ while 1:
debug(DEBUG_VERBOSE, "Object:", obj)
# calculate what symbols and libraries are needed
- needed_symbols = Set()
+ needed_symbols = Set() # Set of (name, weakness-flag)
libraries = Set()
for obj in objects.values():
needed_symbols.merge(undefined_symbols(obj))
@@ -362,7 +380,7 @@ while 1:
# I don't know how to detect those symbols but this seems
# to be the only one and including it on alpha as well
# doesn't hurt. I guess all archs can live with this.
- needed_symbols.add("sys_siglist")
+ needed_symbols.add(("sys_siglist", 1))
# calculate what symbols are present in small_libs
present_symbols = Set()
@@ -372,9 +390,11 @@ while 1:
# are we finished?
num_unresolved = 0
present_symbols_elems = present_symbols.elems()
- for symbol in needed_symbols.elems():
+ unresolved = Set()
+ for (symbol, is_weak) in needed_symbols.elems():
if not symbol in present_symbols_elems:
- debug(DEBUG_SPAM, "Still need:", symbol)
+ debug(DEBUG_SPAM, "Still need:", symbol, `is_weak`)
+ unresolved.add((symbol, is_weak))
num_unresolved = num_unresolved + 1
debug (DEBUG_NORMAL, `needed_symbols.size()`, "symbols,",
@@ -382,7 +402,17 @@ while 1:
if num_unresolved == 0:
break
-
+
+ if unresolved == previous_pass_unresolved:
+ # No progress in last pass. Check all remaining symbols are
+ # weak?
+ for (symbol, is_weak) in unresolved.elems():
+ if not is_weak:
+ raise "Unresolvable symbol " + symbol
+ break
+
+ previous_pass_unresolved = unresolved
+
library_symbols = {}
library_symbols_used = {}
symbol_provider = {}
@@ -410,12 +440,13 @@ while 1:
symbol_provider[symbol] = library
# which symbols are actually used from each lib
- for symbol in needed_symbols.elems():
- try:
+ for (symbol, is_weak) in needed_symbols.elems():
+ if not symbol_provider.has_key(symbol):
+ if not is_weak:
+ raise "No library provides non-weak " + symbol
+ else:
lib = symbol_provider[symbol]
library_symbols_used[lib].add(symbol)
- except KeyError:
- pass
# reduce libraries
for library in libraries.elems():
Reply to: