-
Notifications
You must be signed in to change notification settings - Fork 58
/
gcc-with-cpychecker
executable file
·114 lines (98 loc) · 4.09 KB
/
gcc-with-cpychecker
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/env python
# Copyright 2011 David Malcolm <[email protected]>
# Copyright 2011 Red Hat, Inc.
#
# This is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
# <http://www.gnu.org/licenses/>.
# Harness for invoking GCC with the cpychecker Python code within the python
# plugin, whilst dealing with some options
# (This code runs under the regular Python interpreter, not within gcc)
import argparse
import os
import subprocess
import sys
abspath = os.path.abspath(os.path.dirname(sys.argv[0]))
# By default, look for the plugin relative to this harness. This is intended
# to make it easier during development, so that we can make other projects with
# CC=../../../gcc-python-plugin/gcc-with-cpychecker
# and similar.
#
# When installed, this should be fixed up.
PLUGIN = os.path.join(abspath, 'python.so')
# Similarly, set the location to search for libgcc-c-api.so:
LD_LIBRARY_PATH = os.path.join(abspath, 'gcc-c-api')
if 'LD_LIBRARY_PATH' in os.environ:
LD_LIBRARY_PATH = '%s:%s' % (LD_LIBRARY_PATH, os.environ['LD_LIBRARY_PATH'])
# Create arg parser:
parser = argparse.ArgumentParser(usage='%(prog)s [options] gcc-options')
DEFAULT_MAXTRANS=256
parser.add_argument('--maxtrans',
type=int,
default=DEFAULT_MAXTRANS,
help='Set the maximum number of transitions to consider before pruning the analysis tree (default: %i)' % DEFAULT_MAXTRANS)
parser.add_argument('--dump-json',
action='store_true',
default=False,
help=('Dump a JSON representation of any problems. For'
' example, given a function "foo.c", if any warnings'
' or errors are found in function "bar", a file'
' "foo.c.bar.json" will be written out in JSON'
' form'))
parser.add_argument('--cpychecker-verbose',
action='store_true',
default=False,
help=('Output extra information'))
# Only consume args we understand, leaving the rest for gcc:
ns, other_args = parser.parse_known_args()
if 0:
print(ns)
print(other_args)
# Enable the refcount-checker when running via this script
#
# We would use the regular keyword argument syntax:
# verify_refcounting=True
# but unfortunately gcc's option parser seems to not be able to cope with '='
# within an option's value. So we do it using dictionary syntax instead:
dictstr = '"verify_refcounting":True'
dictstr += ', "verbose":%i' % (ns.cpychecker_verbose)
dictstr += ', "maxtrans":%i' % ns.maxtrans
dictstr += ', "dump_json":%i' % ns.dump_json
cmd = 'from libcpychecker import main; main(**{%s})' % dictstr
# Do not use CC in the environment, to avoid forkbombing when setting
# CC=gcc-with-cpychecker. Instead, use CC_FOR_CPYCHECKER.
if 'CC_FOR_CPYCHECKER' in os.environ:
gcc = os.environ['CC_FOR_CPYCHECKER']
else:
gcc = 'gcc'
args = [gcc,
('-fplugin=%s' % PLUGIN),
('-fplugin-arg-python-command=%s' % cmd)]
args += other_args # (the args we didn't consume)
# Beware of quoting: if the command is quoted within the Popen call, then
# Python interprets it as a string literal, and does nothing.
#
# But if invoking from a shell, you need quotes aroung the command
#
# To add to the fun, "gcc -v" emits it in unquoted form,
# which will need quotes added
env = os.environ.copy()
env['LD_LIBRARY_PATH'] = LD_LIBRARY_PATH
if 0:
print(' '.join(args))
p = subprocess.Popen(args, env=env)
try:
r = p.wait()
except KeyboardInterrupt:
r = 1
sys.exit(r)