diff options
Diffstat (limited to 'buildtools')
-rw-r--r-- | buildtools/wafsamba/symbols.py | 102 |
1 files changed, 82 insertions, 20 deletions
diff --git a/buildtools/wafsamba/symbols.py b/buildtools/wafsamba/symbols.py index 0e862cbe15c..5059c60a45c 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): |