mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
85 lines
3.0 KiB
Python
Executable File
85 lines
3.0 KiB
Python
Executable File
#!/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(
|
|
"(?P<index>\d+) +(?P<object>\S+) +(?P<address>0x[0-9a-fA-F]{16}) "
|
|
"(?P<routine>[^+]+) [+] (?P<offset>\d+)")
|
|
|
|
lines = sys.stdin.readlines()
|
|
|
|
found_stack_trace_start = False
|
|
found_stack_trace_entry = False
|
|
for l in lines:
|
|
l = l.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 l == "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(l)
|
|
# 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()
|