diff options
author | pg <pg@yandex-team.com> | 2025-02-20 10:16:57 +0300 |
---|---|---|
committer | pg <pg@yandex-team.com> | 2025-02-20 10:51:20 +0300 |
commit | 4916a4fc87dd13ae1b8281fc9dab6aa26601cc44 (patch) | |
tree | f1e00ce48e8009e538ca887ac00241fdd4ebfdfb /library/cpp | |
parent | d5474ec47cbc575c8bd55d05fddf2e22eb1f3bf3 (diff) | |
download | ydb-4916a4fc87dd13ae1b8281fc9dab6aa26601cc44.tar.gz |
refactor out sanitizer plugin
commit_hash:d0bd11c053e40d5117172fd59c19b6d6caf6fb8e
Diffstat (limited to 'library/cpp')
-rw-r--r-- | library/cpp/sanitizer/plugin/sanitizer.py | 96 | ||||
-rw-r--r-- | library/cpp/sanitizer/plugin/ya.make | 9 |
2 files changed, 105 insertions, 0 deletions
diff --git a/library/cpp/sanitizer/plugin/sanitizer.py b/library/cpp/sanitizer/plugin/sanitizer.py new file mode 100644 index 0000000000..1653b3a97e --- /dev/null +++ b/library/cpp/sanitizer/plugin/sanitizer.py @@ -0,0 +1,96 @@ +import collections +import os +import sys +import json + + +def get_leaks_suppressions(cmd): + supp, newcmd = [], [] + for arg in cmd: + if arg.endswith(".supp"): + supp.append(arg) + else: + newcmd.append(arg) + return supp, newcmd + + +def fix_sanitize_flag(cmd, clang_ver): + """ + Remove -fsanitize=address flag if sanitazers are linked explicitly for linux target. + """ + for flag in cmd: + if flag.startswith('--target') and 'linux' not in flag.lower(): + # use toolchained sanitize libraries + return cmd + CLANG_RT = 'contrib/libs/clang' + clang_ver + '-rt/lib/' + sanitize_flags = { + '-fsanitize=address': CLANG_RT + 'asan', + '-fsanitize=memory': CLANG_RT + 'msan', + '-fsanitize=leak': CLANG_RT + 'lsan', + '-fsanitize=undefined': CLANG_RT + 'ubsan', + '-fsanitize=thread': CLANG_RT + 'tsan', + } + + used_sanitize_libs = [] + aux = [] + for flag in cmd: + if flag.startswith('-fsanitize-coverage='): + # do not link sanitizer libraries from clang + aux.append('-fno-sanitize-link-runtime') + if flag in sanitize_flags and any(s.startswith(sanitize_flags[flag]) for s in cmd): + # exclude '-fsanitize=' if appropriate library is linked explicitly + continue + if any(flag.startswith(lib) for lib in sanitize_flags.values()): + used_sanitize_libs.append(flag) + continue + aux.append(flag) + + # move sanitize libraries out of the repeatedly searched group of archives + flags = [] + for flag in aux: + if flag == '-Wl,--start-group': + flags += ['-Wl,--whole-archive'] + used_sanitize_libs + ['-Wl,--no-whole-archive'] + flags.append(flag) + + return flags + + +def gen_default_suppressions(inputs, output, source_root): + supp_map = collections.defaultdict(set) + for filename in inputs: + sanitizer = os.path.basename(filename).split('.', 1)[0] + with open(os.path.join(source_root, filename)) as src: + for line in src: + line = line.strip() + if not line or line.startswith('#'): + continue + supp_map[sanitizer].add(line) + + with open(output, "wb") as dst: + for supp_type, supps in supp_map.items(): + dst.write('extern "C" const char *__%s_default_suppressions() {\n' % supp_type) + dst.write(' return "{}";\n'.format('\\n'.join(sorted(supps)))) + dst.write('}\n') + + +def sanitize(cmd): + clang_ver = cmd[cmd.index('--clang-ver') + 1] + source_root = cmd[cmd.index('--source-root') + 1] + cmd = fix_sanitize_flag(cmd, clang_ver) + supp, cmd = get_leaks_suppressions(cmd) + if supp: + src_file = "default_suppressions.cpp" + gen_default_suppressions(supp, src_file, source_root) + cmd += [src_file] + return cmd + + +if __name__ == '__main__': + cmd = sys.argv[1:] + + if 'link_exe.py' in str(cmd): + cmd = sanitize(cmd) + else: + cmd = [s for s in cmd if not s.endswith('.supp')] + + sys.stdout.write(json.dumps(cmd)) diff --git a/library/cpp/sanitizer/plugin/ya.make b/library/cpp/sanitizer/plugin/ya.make new file mode 100644 index 0000000000..0b751fa638 --- /dev/null +++ b/library/cpp/sanitizer/plugin/ya.make @@ -0,0 +1,9 @@ +LIBRARY() + +NO_UTIL() +NO_RUNTIME() +NO_PLATFORM() + +LD_PLUGIN(sanitizer.py) + +END() |