summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buildtools/wafsamba/symbols.py102
1 files changed, 82 insertions, 20 deletions
diff --git a/buildtools/wafsamba/symbols.py b/buildtools/wafsamba/symbols.py
index 0e862cbe15..5059c60a45 100644
--- a/buildtools/wafsamba/symbols.py
+++ b/buildtools/wafsamba/symbols.py
@@ -17,6 +17,7 @@ from samba_utils import *
#
# bld.env.syslib_symbols: dictionary mapping system library name to set of symbols
# for that library
+# bld.env.library_dict : dictionary mapping built library paths to subsystem names
#
# LOCAL_CACHE(bld, 'TARGET_TYPE') : dictionary mapping subsystem name to target type
@@ -30,11 +31,11 @@ def symbols_extract(objfiles, dynamic=False):
if dynamic:
# needed for some .so files
cmd.append("-D")
- cmd.extend(objfiles)
+ cmd.extend(list(objfiles))
nmpipe = subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout
if len(objfiles) == 1:
- filename = objfiles[0]
+ filename = list(objfiles)[0]
ret[filename] = { "PUBLIC": set(), "UNDEFINED" : set()}
for line in nmpipe:
@@ -68,6 +69,35 @@ def real_name(name):
return name
+def get_ldd_libs(bld, binname):
+ '''find the list of linked libraries for any binary or library
+ binname is the path to the binary/library on disk
+ '''
+ ret = set()
+ lddpipe = subprocess.Popen(['ldd', binname], stdout=subprocess.PIPE).stdout
+ for line in lddpipe:
+ line = line.strip()
+ cols = line.split(" ")
+ if len(cols) < 3 or cols[1] != "=>" or cols[2] == '':
+ continue
+ ret.add(os.path.realpath(cols[2]))
+ return ret
+
+
+def get_ldd_libs_recursive(bld, binname, seen=set()):
+ '''find the recursive list of linked libraries for any binary or library
+ binname is the path to the binary/library on disk. seen is a set used
+ to prevent loops
+ '''
+ if binname in seen:
+ return set()
+ ret = get_ldd_libs(bld, binname)
+ seen.add(binname)
+ for lib in ret:
+ ret = ret.union(get_ldd_libs_recursive(bld, lib, seen))
+ return ret
+
+
def find_syslib_path(bld, libname, deps):
'''find the path to the syslib we will link against'''
# the strategy is to use the targets that depend on the library, and run ldd
@@ -160,6 +190,20 @@ def build_symbol_sets(bld, tgt_list):
bld.env.used_symbols[name] = bld.env.used_symbols[name].union(t2.used_symbols)
+def build_library_dict(bld, tgt_list):
+ '''build the library_dict dictionary'''
+
+ if bld.env.library_dict:
+ return
+
+ bld.env.library_dict = {}
+
+ for t in tgt_list:
+ if t.samba_type in [ 'LIBRARY', 'PYTHON' ]:
+ linkpath = os.path.realpath(t.link_task.outputs[0].abspath(bld.env))
+ bld.env.library_dict[linkpath] = t.sname
+
+
def build_syslib_sets(bld, tgt_list):
'''build the public_symbols for all syslibs'''
@@ -444,6 +488,37 @@ def symbols_whyneeded(task):
Logs.info("target '%s' uses symbols %s from '%s'" % (target, overlap, subsystem))
+def report_duplicate(bld, binname, sym, libs):
+ '''report duplicated symbols'''
+ if sym in ['_init', '_fini']:
+ return
+ libnames = []
+ for lib in libs:
+ if lib in bld.env.library_dict:
+ libnames.append(bld.env.library_dict[lib])
+ else:
+ libnames.append(lib)
+ print("%s: Symbol %s linked in multiple libraries %s" % (binname, sym, libnames))
+
+
+def symbols_dupcheck_binary(bld, binname):
+ '''check for duplicated symbols in one binary'''
+ libs = get_ldd_libs_recursive(bld, binname)
+
+ symlist = symbols_extract(libs, dynamic=True)
+
+ symmap = {}
+ for libpath in symlist:
+ for sym in symlist[libpath]['PUBLIC']:
+ if not sym in symmap:
+ symmap[sym] = set()
+ symmap[sym].add(libpath)
+ for sym in symmap:
+ if len(symmap[sym]) > 1:
+ for libpath in symmap[sym]:
+ if libpath in bld.env.library_dict:
+ report_duplicate(bld, binname, sym, symmap[sym])
+ break
def symbols_dupcheck(task):
'''check for symbols defined in two different subsystems'''
@@ -452,25 +527,12 @@ def symbols_dupcheck(task):
targets = LOCAL_CACHE(bld, 'TARGET_TYPE')
- Logs.info("Checking for duplicate symbols")
- for sym in bld.env.symbol_map:
- subsystems = set(bld.env.symbol_map[sym])
- if len(subsystems) == 1:
- continue
-
- if sym in ['main', '_init', '_fini', 'init_samba_module', 'samba_init_module', 'ldb_init_module' ]:
- # these are expected to be in many subsystems
- continue
+ build_library_dict(bld, tgt_list)
+ for t in tgt_list:
+ if t.samba_type == 'BINARY':
+ binname = os_path_relpath(t.link_task.outputs[0].abspath(bld.env), os.getcwd())
+ symbols_dupcheck_binary(bld, binname)
- # if all of them are in system libraries, we can ignore them. This copes
- # with the duplication between libc, libpthread and libattr
- all_syslib = True
- for s in subsystems:
- if s != 'c' and (not s in targets or targets[s] != 'SYSLIB'):
- all_syslib = False
- if all_syslib:
- continue
- Logs.info("symbol %s appears in %s" % (sym, subsystems))
def SYMBOL_CHECK(bld):