diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:04:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:04:05 +0000 |
commit | 676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63 (patch) | |
tree | 02a1ac369cb734d0abfa5000dd86e5b7797e6a74 /tools/scan-build-py/libscanbuild | |
parent | c7e70c433efc6953dc3888b9fbf9f3512d7da2b0 (diff) |
Diffstat (limited to 'tools/scan-build-py/libscanbuild')
-rw-r--r-- | tools/scan-build-py/libscanbuild/__init__.py | 2 | ||||
-rw-r--r-- | tools/scan-build-py/libscanbuild/analyze.py | 120 | ||||
-rw-r--r-- | tools/scan-build-py/libscanbuild/arguments.py | 29 | ||||
-rw-r--r-- | tools/scan-build-py/libscanbuild/clang.py | 6 |
4 files changed, 79 insertions, 78 deletions
diff --git a/tools/scan-build-py/libscanbuild/__init__.py b/tools/scan-build-py/libscanbuild/__init__.py index e7b74879167e5..903207c6be090 100644 --- a/tools/scan-build-py/libscanbuild/__init__.py +++ b/tools/scan-build-py/libscanbuild/__init__.py @@ -20,7 +20,7 @@ ENVIRONMENT_KEY = 'INTERCEPT_BUILD' Execution = collections.namedtuple('Execution', ['pid', 'cwd', 'cmd']) CtuConfig = collections.namedtuple('CtuConfig', ['collect', 'analyze', 'dir', - 'func_map_cmd']) + 'extdef_map_cmd']) def duplicate_check(method): diff --git a/tools/scan-build-py/libscanbuild/analyze.py b/tools/scan-build-py/libscanbuild/analyze.py index 5a7cc20a517e3..ab8ea62f46fe8 100644 --- a/tools/scan-build-py/libscanbuild/analyze.py +++ b/tools/scan-build-py/libscanbuild/analyze.py @@ -42,8 +42,8 @@ __all__ = ['scan_build', 'analyze_build', 'analyze_compiler_wrapper'] COMPILER_WRAPPER_CC = 'analyze-cc' COMPILER_WRAPPER_CXX = 'analyze-c++' -CTU_FUNCTION_MAP_FILENAME = 'externalFnMap.txt' -CTU_TEMP_FNMAP_FOLDER = 'tmpExternalFnMaps' +CTU_EXTDEF_MAP_FILENAME = 'externalDefMap.txt' +CTU_TEMP_DEFMAP_FOLDER = 'tmpExternalDefMaps' @command_entry_point @@ -117,9 +117,9 @@ def get_ctu_config_from_args(args): CtuConfig(collect=args.ctu_phases.collect, analyze=args.ctu_phases.analyze, dir=args.ctu_dir, - func_map_cmd=args.func_map_cmd) + extdef_map_cmd=args.extdef_map_cmd) if hasattr(args, 'ctu_phases') and hasattr(args.ctu_phases, 'dir') - else CtuConfig(collect=False, analyze=False, dir='', func_map_cmd='')) + else CtuConfig(collect=False, analyze=False, dir='', extdef_map_cmd='')) def get_ctu_config_from_json(ctu_conf_json): @@ -130,23 +130,24 @@ def get_ctu_config_from_json(ctu_conf_json): return CtuConfig(collect=ctu_config[0], analyze=ctu_config[1], dir=ctu_config[2], - func_map_cmd=ctu_config[3]) + extdef_map_cmd=ctu_config[3]) -def create_global_ctu_function_map(func_map_lines): - """ Takes iterator of individual function maps and creates a global map - keeping only unique names. We leave conflicting names out of CTU. +def create_global_ctu_extdef_map(extdef_map_lines): + """ Takes iterator of individual external definition maps and creates a + global map keeping only unique names. We leave conflicting names out of + CTU. - :param func_map_lines: Contains the id of a function (mangled name) and + :param extdef_map_lines: Contains the id of a definition (mangled name) and the originating source (the corresponding AST file) name. - :type func_map_lines: Iterator of str. + :type extdef_map_lines: Iterator of str. :returns: Mangled name - AST file pairs. :rtype: List of (str, str) tuples. """ mangled_to_asts = defaultdict(set) - for line in func_map_lines: + for line in extdef_map_lines: mangled_name, ast_file = line.strip().split(' ', 1) mangled_to_asts[mangled_name].add(ast_file) @@ -159,20 +160,20 @@ def create_global_ctu_function_map(func_map_lines): return mangled_ast_pairs -def merge_ctu_func_maps(ctudir): - """ Merge individual function maps into a global one. +def merge_ctu_extdef_maps(ctudir): + """ Merge individual external definition maps into a global one. As the collect phase runs parallel on multiple threads, all compilation - units are separately mapped into a temporary file in CTU_TEMP_FNMAP_FOLDER. - These function maps contain the mangled names of functions and the source - (AST generated from the source) which had them. + units are separately mapped into a temporary file in CTU_TEMP_DEFMAP_FOLDER. + These definition maps contain the mangled names and the source + (AST generated from the source) which had their definition. These files should be merged at the end into a global map file: - CTU_FUNCTION_MAP_FILENAME.""" + CTU_EXTDEF_MAP_FILENAME.""" - def generate_func_map_lines(fnmap_dir): + def generate_extdef_map_lines(extdefmap_dir): """ Iterate over all lines of input files in a determined order. """ - files = glob.glob(os.path.join(fnmap_dir, '*')) + files = glob.glob(os.path.join(extdefmap_dir, '*')) files.sort() for filename in files: with open(filename, 'r') as in_file: @@ -180,11 +181,11 @@ def merge_ctu_func_maps(ctudir): yield line def write_global_map(arch, mangled_ast_pairs): - """ Write (mangled function name, ast file) pairs into final file. """ + """ Write (mangled name, ast file) pairs into final file. """ - extern_fns_map_file = os.path.join(ctudir, arch, - CTU_FUNCTION_MAP_FILENAME) - with open(extern_fns_map_file, 'w') as out_file: + extern_defs_map_file = os.path.join(ctudir, arch, + CTU_EXTDEF_MAP_FILENAME) + with open(extern_defs_map_file, 'w') as out_file: for mangled_name, ast_file in mangled_ast_pairs: out_file.write('%s %s\n' % (mangled_name, ast_file)) @@ -192,15 +193,15 @@ def merge_ctu_func_maps(ctudir): for triple_path in triple_arches: if os.path.isdir(triple_path): triple_arch = os.path.basename(triple_path) - fnmap_dir = os.path.join(ctudir, triple_arch, - CTU_TEMP_FNMAP_FOLDER) + extdefmap_dir = os.path.join(ctudir, triple_arch, + CTU_TEMP_DEFMAP_FOLDER) - func_map_lines = generate_func_map_lines(fnmap_dir) - mangled_ast_pairs = create_global_ctu_function_map(func_map_lines) + extdef_map_lines = generate_extdef_map_lines(extdefmap_dir) + mangled_ast_pairs = create_global_ctu_extdef_map(extdef_map_lines) write_global_map(triple_arch, mangled_ast_pairs) # Remove all temporary files - shutil.rmtree(fnmap_dir, ignore_errors=True) + shutil.rmtree(extdefmap_dir, ignore_errors=True) def run_analyzer_parallel(args): @@ -251,21 +252,21 @@ def govern_analyzer_runs(args): # left so multiple analyze runs can use the same data gathered by a single # collection run. if ctu_config.collect and ctu_config.analyze: - # CTU strings are coming from args.ctu_dir and func_map_cmd, + # CTU strings are coming from args.ctu_dir and extdef_map_cmd, # so we can leave it empty args.ctu_phases = CtuConfig(collect=True, analyze=False, - dir='', func_map_cmd='') + dir='', extdef_map_cmd='') run_analyzer_parallel(args) - merge_ctu_func_maps(ctu_config.dir) + merge_ctu_extdef_maps(ctu_config.dir) args.ctu_phases = CtuConfig(collect=False, analyze=True, - dir='', func_map_cmd='') + dir='', extdef_map_cmd='') run_analyzer_parallel(args) shutil.rmtree(ctu_config.dir, ignore_errors=True) else: # Single runs (collect or analyze) are launched from here. run_analyzer_parallel(args) if ctu_config.collect: - merge_ctu_func_maps(ctu_config.dir) + merge_ctu_extdef_maps(ctu_config.dir) def setup_environment(args): @@ -395,8 +396,6 @@ def analyzer_params(args): if args.disable_checker: checkers = ','.join(args.disable_checker) result.extend(['-analyzer-disable-checker', checkers]) - if os.getenv('UBIVIZ'): - result.append('-analyzer-viz-egraph-ubigraph') return prefix_with('-Xclang', result) @@ -546,20 +545,20 @@ def run_analyzer(opts, continuation=report_failure): return result -def func_map_list_src_to_ast(func_src_list): - """ Turns textual function map list with source files into a - function map list with ast files. """ +def extdef_map_list_src_to_ast(extdef_src_list): + """ Turns textual external definition map list with source files into an + external definition map list with ast files. """ - func_ast_list = [] - for fn_src_txt in func_src_list: - mangled_name, path = fn_src_txt.split(" ", 1) + extdef_ast_list = [] + for extdef_src_txt in extdef_src_list: + mangled_name, path = extdef_src_txt.split(" ", 1) # Normalize path on windows as well path = os.path.splitdrive(path)[1] # Make relative path out of absolute path = path[1:] if path[0] == os.sep else path ast_path = os.path.join("ast", path + ".ast") - func_ast_list.append(mangled_name + " " + ast_path) - return func_ast_list + extdef_ast_list.append(mangled_name + " " + ast_path) + return extdef_ast_list @require(['clang', 'directory', 'flags', 'direct_args', 'file', 'ctu']) @@ -590,37 +589,38 @@ def ctu_collect_phase(opts): logging.debug("Generating AST using '%s'", ast_command) run_command(ast_command, cwd=opts['directory']) - def map_functions(triple_arch): - """ Generate function map file for the current source. """ + def map_extdefs(triple_arch): + """ Generate external definition map file for the current source. """ args = opts['direct_args'] + opts['flags'] - funcmap_command = [opts['ctu'].func_map_cmd] - funcmap_command.append(opts['file']) - funcmap_command.append('--') - funcmap_command.extend(args) - logging.debug("Generating function map using '%s'", funcmap_command) - func_src_list = run_command(funcmap_command, cwd=opts['directory']) - func_ast_list = func_map_list_src_to_ast(func_src_list) - extern_fns_map_folder = os.path.join(opts['ctu'].dir, triple_arch, - CTU_TEMP_FNMAP_FOLDER) - if not os.path.isdir(extern_fns_map_folder): + extdefmap_command = [opts['ctu'].extdef_map_cmd] + extdefmap_command.append(opts['file']) + extdefmap_command.append('--') + extdefmap_command.extend(args) + logging.debug("Generating external definition map using '%s'", + extdefmap_command) + extdef_src_list = run_command(extdefmap_command, cwd=opts['directory']) + extdef_ast_list = extdef_map_list_src_to_ast(extdef_src_list) + extern_defs_map_folder = os.path.join(opts['ctu'].dir, triple_arch, + CTU_TEMP_DEFMAP_FOLDER) + if not os.path.isdir(extern_defs_map_folder): try: - os.makedirs(extern_fns_map_folder) + os.makedirs(extern_defs_map_folder) except OSError: # In case an other process already created it. pass - if func_ast_list: + if extdef_ast_list: with tempfile.NamedTemporaryFile(mode='w', - dir=extern_fns_map_folder, + dir=extern_defs_map_folder, delete=False) as out_file: - out_file.write("\n".join(func_ast_list) + "\n") + out_file.write("\n".join(extdef_ast_list) + "\n") cwd = opts['directory'] cmd = [opts['clang'], '--analyze'] + opts['direct_args'] + opts['flags'] \ + [opts['file']] triple_arch = get_triple_arch(cmd, cwd) generate_ast(triple_arch) - map_functions(triple_arch) + map_extdefs(triple_arch) @require(['ctu']) diff --git a/tools/scan-build-py/libscanbuild/arguments.py b/tools/scan-build-py/libscanbuild/arguments.py index a5d0c6bda6613..58c56d2b6d290 100644 --- a/tools/scan-build-py/libscanbuild/arguments.py +++ b/tools/scan-build-py/libscanbuild/arguments.py @@ -12,6 +12,7 @@ earlier.) It also implements basic validation methods, related to the command. Validations are mostly calling specific help methods, or mangling values. """ +from __future__ import absolute_import, division, print_function import os import sys @@ -134,10 +135,10 @@ def validate_args_for_analyze(parser, args, from_build_command): if args.ctu_phases.analyze and not args.ctu_phases.collect \ and not os.path.exists(args.ctu_dir): parser.error(message='missing CTU directory') - # Check CTU capability via checking clang-func-mapping - if not is_ctu_capable(args.func_map_cmd): + # Check CTU capability via checking clang-extdef-mapping + if not is_ctu_capable(args.extdef_map_cmd): parser.error(message="""This version of clang does not support CTU - functionality or clang-func-mapping command not found.""") + functionality or clang-extdef-mapping command not found.""") def create_intercept_parser(): @@ -365,7 +366,7 @@ def create_analyze_parser(from_build_command): '--ctu', action='store_const', const=CtuConfig(collect=True, analyze=True, - dir='', func_map_cmd=''), + dir='', extdef_map_cmd=''), dest='ctu_phases', help="""Perform cross translation unit (ctu) analysis (both collect and analyze phases) using default <ctu-dir> for temporary output. @@ -381,7 +382,7 @@ def create_analyze_parser(from_build_command): '--ctu-collect-only', action='store_const', const=CtuConfig(collect=True, analyze=False, - dir='', func_map_cmd=''), + dir='', extdef_map_cmd=''), dest='ctu_phases', help="""Perform only the collect phase of ctu. Keep <ctu-dir> for further use.""") @@ -389,20 +390,20 @@ def create_analyze_parser(from_build_command): '--ctu-analyze-only', action='store_const', const=CtuConfig(collect=False, analyze=True, - dir='', func_map_cmd=''), + dir='', extdef_map_cmd=''), dest='ctu_phases', help="""Perform only the analyze phase of ctu. <ctu-dir> should be present and will not be removed after analysis.""") ctu.add_argument( - '--use-func-map-cmd', + '--use-extdef-map-cmd', metavar='<path>', - dest='func_map_cmd', - default='clang-func-mapping', - help="""'%(prog)s' uses the 'clang-func-mapping' executable - relative to itself for generating function maps for static - analysis. One can override this behavior with this option by using - the 'clang-func-mapping' packaged with Xcode (on OS X) or from the - PATH.""") + dest='extdef_map_cmd', + default='clang-extdef-mapping', + help="""'%(prog)s' uses the 'clang-extdef-mapping' executable + relative to itself for generating external definition maps for + static analysis. One can override this behavior with this option + by using the 'clang-extdef-mapping' packaged with Xcode (on OS X) + or from the PATH.""") return parser diff --git a/tools/scan-build-py/libscanbuild/clang.py b/tools/scan-build-py/libscanbuild/clang.py index ab422066cab12..0cbfdb648f6a9 100644 --- a/tools/scan-build-py/libscanbuild/clang.py +++ b/tools/scan-build-py/libscanbuild/clang.py @@ -156,12 +156,12 @@ def get_checkers(clang, plugins): return checkers -def is_ctu_capable(func_map_cmd): - """ Detects if the current (or given) clang and function mapping +def is_ctu_capable(extdef_map_cmd): + """ Detects if the current (or given) clang and external definition mapping executables are CTU compatible. """ try: - run_command([func_map_cmd, '-version']) + run_command([extdef_map_cmd, '-version']) except (OSError, subprocess.CalledProcessError): return False return True |