diff --git a/clang/utils/creduce-clang-crash.py b/clang/utils/creduce-clang-crash.py index b69d6efc248184..cdc639c6f85481 100755 --- a/clang/utils/creduce-clang-crash.py +++ b/clang/utils/creduce-clang-crash.py @@ -23,7 +23,6 @@ verbose = False creduce_cmd = None clang_cmd = None -not_cmd = None def verbose_print(*args, **kwargs): if verbose: @@ -77,7 +76,7 @@ def __init__(self, crash_script, file_to_reduce): 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 @@ def read_expected_output(self): 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 @@ def read_expected_output(self): # 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 @@ def check_expected_output(self, args=None, filename=None): 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])