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

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: