forked from swiftlang/swift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
backtrace-check
executable file
·84 lines (68 loc) · 2.96 KB
/
backtrace-check
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
#!/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()