blob: a304f68bc22ed98b4deed9ae943c761677fcbee4 [file] [log] [blame]
#!/usr/bin/env python
# This script uses a regex to validate the output of our backtraces.
# The layout we assume is:
#
# <frame number> <library name> <address> <demangled name> + <offset>
#
# It currently just checks that the backtrace results in at least one correctly
# formatted entry. It does not directly validate the input since the output
# would not be robust against standard library changes.
#
# TODO: We could have the user pass in the frame number, library name, and
# demangled name. These we can always validate as true in a robust way. On the
# other hand, address and offset are more difficult to validate in a robust way
# in the face of small codegen differences, so without any further thought I
# imagine we can just check the format.
#
# 11 libswiftCore.dylib 0x000000000dce84d0l _fatalErrorMessage(StaticString,
# StaticString, StaticString, UInt, flags : UInt32) -> () + 444
from __future__ import print_function
import argparse
import re
import sys
def main():
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description="""Checks that a stacktrace dump follows canonical
formatting.""")
parser.add_argument(
"-u", "--check-unavailable", action='store_true',
help="Checks if any symbols were unavailable")
args = parser.parse_args()
TARGET_RE = re.compile(
r"(?P<index>\d+) +(?P<object>\S+) +(?P<address>0x[0-9a-fA-F]{16}) "
r"(?P<routine>[^+]+) [+] (?P<offset>\d+)")
lines = sys.stdin.readlines()
found_stack_trace_start = False
found_stack_trace_entry = False
for line in lines:
line = line.rstrip("\n")
# First see if we found the start of our stack trace start. If so, set
# the found stack trace flag and continue.
if line == "Current stack trace:":
assert(not found_stack_trace_start)
found_stack_trace_start = True
continue
# Otherwise, if we have not yet found the stack trace start, continue.
# We need to find the stack trace start line.
if not found_stack_trace_start:
continue
# Ok, we are in the middle of matching a stack trace entry.
m = TARGET_RE.match(line)
# If we fail to match, we have exited the stack trace entry region
if m is None:
break
# At this point, we know that we have some sort of match.
found_stack_trace_entry = True
print("Stack Trace Entry:")
print("\tIndex: '%(index)s'\n\tObject File: '%(object)s'\n\tAddress: "
"'%(address)s'\n\tRoutine: '%(routine)s'\n\tOffset: '%(offset)s'"
"\n" % m.groupdict())
# Check for unavailable symbols, if that was requested.
if args.check_unavailable:
assert("unavailable" not in m.group("routine"))
# Once we have processed all of the lines, make sure that we found at least
# one stack trace entry.
assert(found_stack_trace_entry)
if __name__ == '__main__':
main()