Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add --gcc-analyzer-bin option to gcc plug-in #41

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion py/common/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ def translate_one(i):
return cmd_out.lstrip()


def write_toolver(ini_writer, tool_key, ver):
ini_writer.append("analyzer-version-%s" % tool_key, ver)


def write_toolver_from_rpmlist(results, mock, tool, tool_key):
cmd = "grep '^%s-[0-9]' %s/rpm-list-mock.txt" % (tool, results.dbgdir)
(rc, nvr) = results.get_cmd_output(cmd)
Expand All @@ -56,7 +60,7 @@ def write_toolver_from_rpmlist(results, mock, tool, tool_key):
return rc

ver = re.sub("-[0-9].*$", "", re.sub("^%s-" % tool, "", nvr.strip()))
results.ini_writer.append("analyzer-version-%s" % tool_key, ver)
write_toolver(results.ini_writer, tool_key, ver)
return 0


Expand Down
7 changes: 4 additions & 3 deletions py/csmock
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ class ScanProps:
self.pkg = None
self.imp_checker_set = set()
self.imp_csgrep_filters = []
self.cswrap_path = None

def enable_cswrap(self):
if self.cswrap_enabled:
Expand All @@ -435,10 +436,10 @@ class ScanProps:
cmd = ["cswrap", "--print-path-to-wrap"]
subproc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(out, _) = subproc.communicate()
cswrap_path = out.decode("utf8").strip()
self.cswrap_path = out.decode("utf8").strip()

self.copy_in_files += ["/usr/bin/cswrap", cswrap_path]
self.path = [cswrap_path] + self.path
self.copy_in_files += ["/usr/bin/cswrap", self.cswrap_path]
self.path = [self.cswrap_path] + self.path
self.env["CSWRAP_CAP_FILE"] = "/builddir/cswrap-capture.err"
self.env["CSWRAP_TIMEOUT"] = "%d" % self.cswrap_timeout
self.env["CSWRAP_TIMEOUT_FOR"] = ":"
Expand Down
53 changes: 47 additions & 6 deletions py/plugins/gcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@

from csmock.common.cflags import add_custom_flag_opts, flags_by_warning_level

CSGCCA_BIN="/usr/bin/csgcca"
CSGCCA_BIN = "/usr/bin/csgcca"

CSMOCK_GCC_WRAPPER_NAME = 'csmock-gcc-wrapper'
CSMOCK_GCC_WRAPPER_PATH = '/usr/bin/%s' % CSMOCK_GCC_WRAPPER_NAME
CSMOCK_GCC_WRAPPER_TEMPLATE = '#!/bin/bash\n' \
'exec %s "$@"'


class PluginProps:
def __init__(self):
Expand Down Expand Up @@ -64,6 +70,10 @@ def init_parser(self, parser):
"--gcc-analyze", action="store_true",
help="run `gcc -fanalyzer` in a separate process")

parser.add_argument(
"--gcc-analyzer-bin", action="store",
help="use custom build of gcc to perform scan")

parser.add_argument(
"--gcc-analyze-add-flag", action="append", default=[],
help="append the given flag when invoking `gcc -fanalyzer` \
Expand Down Expand Up @@ -98,7 +108,9 @@ def handle_args(self, parser, args, props):
self.enable()
self.flags = flags_by_warning_level(args.gcc_warning_level)

if args.gcc_analyze or getattr(args, "all_tools", False):
if args.gcc_analyze or \
args.gcc_analyzer_bin or \
getattr(args, "all_tools", False):
self.enable()
# resolve csgcca_path by querying csclng binary
cmd = [CSGCCA_BIN, "--print-path-to-wrap"]
Expand Down Expand Up @@ -162,13 +174,35 @@ def handle_args(self, parser, args, props):

if self.csgcca_path is not None:
def csgcca_hook(results, mock):
analyzer_bin = args.gcc_analyzer_bin if args.gcc_analyzer_bin else "gcc"
cmd = "echo 'int main() {}'"
cmd += " | gcc -xc - -c -o /dev/null"
cmd += " | %s -xc - -c -o /dev/null" % analyzer_bin
cmd += " -fanalyzer -fdiagnostics-path-format=separate-events"
if 0 != mock.exec_mockbuild_cmd(cmd):
results.error("`gcc -fanalyzer` does not seem to work, disabling the tool", ec=0)
results.error("`%s -fanalyzer` does not seem to work, "
"disabling the tool" % analyzer_bin, ec=0)
return 0

if args.gcc_analyzer_bin:
wrapper_script = CSMOCK_GCC_WRAPPER_TEMPLATE % analyzer_bin
cmd = "echo '%s' > %s && chmod 755 %s" % \
(wrapper_script,
CSMOCK_GCC_WRAPPER_PATH,
CSMOCK_GCC_WRAPPER_PATH)
rv = mock.exec_chroot_cmd(cmd)
if 0 != rv:
results.error("failed to create csmock gcc wrapper script")
return rv

cmd = "ln -sf ../../bin/cswrap %s/%s" % \
(props.cswrap_path, CSMOCK_GCC_WRAPPER_NAME)
rv = mock.exec_chroot_cmd(cmd)
if 0 != rv:
results.error("failed to create csmock gcc wrapper symlink")
return rv

props.env["CSGCCA_ANALYZER_BIN"] = CSMOCK_GCC_WRAPPER_NAME

# XXX: changing props this way is extremely fragile
# insert csgcca right before cswrap to avoid chaining
# csclng/cscppc while invoking `gcc -fanalyzer`
Expand All @@ -179,13 +213,20 @@ def csgcca_hook(results, mock):
break
props.path.insert(idx_cswrap, self.csgcca_path)

props.env["CSWRAP_TIMEOUT_FOR"] += ":gcc"
props.env["CSWRAP_TIMEOUT_FOR"] += ":%s" % (CSMOCK_GCC_WRAPPER_NAME if args.gcc_analyzer_bin else "gcc")
if args.gcc_analyze_add_flag:
# propagate custom GCC analyzer flags
props.env["CSGCCA_ADD_OPTS"] = csmock.common.cflags.serialize_flags(args.gcc_analyze_add_flag)

# record that `gcc -fanalyzer` was used for this scan
csmock.common.util.write_toolver_from_rpmlist(results, mock, "gcc", "gcc-analyzer")
cmd = mock.get_mock_cmd(["--chroot", "%s --version" % analyzer_bin])
(rc, ver) = results.get_cmd_output(cmd, shell=False)
if rc != 0:
return rc
ver = ver.partition('\n')[0].strip()
ver = ver.split(' ')[2]
csmock.common.util.write_toolver(results.ini_writer, "gcc-analyzer", ver)

return 0

props.post_depinst_hooks += [csgcca_hook]