mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-25 06:40:18 +00:00
Some updates/fixes to the creduce script.
This was motivated by changes to llvm's `not --crash` disabling symbolization but I ended up removing `not` from the script entirely because it returns differently depending on whether clang "crashes" or exits for some other reason. The script had to choose between calling `not` and `not --crash` and sometimes it was wrong. The script also now disables symbolization when we don't read the stack trace because symbolizing is kind of slow. Differential Revision: https://reviews.llvm.org/D91372
This commit is contained in:
parent
cf6565f6d0
commit
0c80b542d3
@ -23,7 +23,6 @@ from distutils.spawn import find_executable
|
||||
verbose = False
|
||||
creduce_cmd = None
|
||||
clang_cmd = None
|
||||
not_cmd = None
|
||||
|
||||
def verbose_print(*args, **kwargs):
|
||||
if verbose:
|
||||
@ -77,7 +76,7 @@ class Reduce(object):
|
||||
self.clang = clang_cmd
|
||||
self.clang_args = []
|
||||
self.expected_output = []
|
||||
self.is_crash = True
|
||||
self.needs_stack_trace = False
|
||||
self.creduce_flags = ["--tidy"]
|
||||
|
||||
self.read_clang_args(crash_script, file_to_reduce)
|
||||
@ -128,23 +127,20 @@ class Reduce(object):
|
||||
crash_output = re.sub(ansi_escape, '', crash_output.decode('utf-8'))
|
||||
|
||||
# Look for specific error messages
|
||||
regexes = [r"Assertion `(.+)' failed", # Linux assert()
|
||||
r"Assertion failed: (.+),", # FreeBSD/Mac assert()
|
||||
r"fatal error: error in backend: (.+)",
|
||||
r"LLVM ERROR: (.+)",
|
||||
r"UNREACHABLE executed (at .+)?!",
|
||||
r"LLVM IR generation of declaration '(.+)'",
|
||||
r"Generating code for declaration '(.+)'",
|
||||
r"\*\*\* Bad machine code: (.+) \*\*\*"]
|
||||
regexes = [r"Assertion .+ failed", # Linux assert()
|
||||
r"Assertion failed: .+,", # FreeBSD/Mac assert()
|
||||
r"fatal error: error in backend: .+",
|
||||
r"LLVM ERROR: .+",
|
||||
r"UNREACHABLE executed at .+?!",
|
||||
r"LLVM IR generation of declaration '.+'",
|
||||
r"Generating code for declaration '.+'",
|
||||
r"\*\*\* Bad machine code: .+ \*\*\*"]
|
||||
for msg_re in regexes:
|
||||
match = re.search(msg_re, crash_output)
|
||||
if match:
|
||||
msg = match.group(1)
|
||||
msg = match.group(0)
|
||||
result = [msg]
|
||||
print("Found message:", msg)
|
||||
|
||||
if "fatal error:" in msg_re:
|
||||
self.is_crash = False
|
||||
break
|
||||
|
||||
# If no message was found, use the top five stack trace functions,
|
||||
@ -152,12 +148,15 @@ class Reduce(object):
|
||||
# Five is a somewhat arbitrary number; the goal is to get a small number
|
||||
# of identifying functions with some leeway for common functions
|
||||
if not result:
|
||||
self.needs_stack_trace = True
|
||||
stacktrace_re = r'[0-9]+\s+0[xX][0-9a-fA-F]+\s*([^(]+)\('
|
||||
filters = ["PrintStackTraceSignalHandler",
|
||||
"llvm::sys::RunSignalHandlers",
|
||||
"SignalHandler", "__restore_rt", "gsignal", "abort"]
|
||||
filters = ["PrintStackTrace", "RunSignalHandlers", "CleanupOnSignal",
|
||||
"HandleCrash", "SignalHandler", "__restore_rt", "gsignal", "abort"]
|
||||
def skip_function(func_name):
|
||||
return any(name in func_name for name in filters)
|
||||
|
||||
matches = re.findall(stacktrace_re, crash_output)
|
||||
result = [x for x in matches if x and x.strip() not in filters][:5]
|
||||
result = [x for x in matches if x and not skip_function(x)][:5]
|
||||
for msg in result:
|
||||
print("Found stack trace function:", msg)
|
||||
|
||||
@ -184,10 +183,17 @@ class Reduce(object):
|
||||
def write_interestingness_test(self):
|
||||
print("\nCreating the interestingness test...")
|
||||
|
||||
crash_flag = "--crash" if self.is_crash else ""
|
||||
# Disable symbolization if it's not required to avoid slow symbolization.
|
||||
disable_symbolization = ''
|
||||
if not self.needs_stack_trace:
|
||||
disable_symbolization = 'export LLVM_DISABLE_SYMBOLIZATION=1'
|
||||
|
||||
output = "#!/bin/bash\n%s %s %s >& t.log || exit 1\n" % \
|
||||
(pipes.quote(not_cmd), crash_flag, quote_cmd(self.get_crash_cmd()))
|
||||
output = """#!/bin/bash
|
||||
%s
|
||||
if %s >& t.log ; then
|
||||
exit 1
|
||||
fi
|
||||
""" % (disable_symbolization, quote_cmd(self.get_crash_cmd()))
|
||||
|
||||
for msg in self.expected_output:
|
||||
output += 'grep -F %s t.log || exit 1\n' % pipes.quote(msg)
|
||||
@ -372,7 +378,6 @@ def main():
|
||||
global verbose
|
||||
global creduce_cmd
|
||||
global clang_cmd
|
||||
global not_cmd
|
||||
|
||||
parser = ArgumentParser(description=__doc__,
|
||||
formatter_class=RawTextHelpFormatter)
|
||||
@ -382,9 +387,6 @@ def main():
|
||||
help="Name of the file to be reduced.")
|
||||
parser.add_argument('--llvm-bin', dest='llvm_bin', type=str,
|
||||
help="Path to the LLVM bin directory.")
|
||||
parser.add_argument('--llvm-not', dest='llvm_not', type=str,
|
||||
help="The path to the `not` executable. "
|
||||
"By default uses the llvm-bin directory.")
|
||||
parser.add_argument('--clang', dest='clang', type=str,
|
||||
help="The path to the `clang` executable. "
|
||||
"By default uses the llvm-bin directory.")
|
||||
@ -398,7 +400,6 @@ def main():
|
||||
llvm_bin = os.path.abspath(args.llvm_bin) if args.llvm_bin else None
|
||||
creduce_cmd = check_cmd('creduce', None, args.creduce)
|
||||
clang_cmd = check_cmd('clang', llvm_bin, args.clang)
|
||||
not_cmd = check_cmd('not', llvm_bin, args.llvm_not)
|
||||
|
||||
crash_script = check_file(args.crash_script[0])
|
||||
file_to_reduce = check_file(args.file_to_reduce[0])
|
||||
|
Loading…
Reference in New Issue
Block a user