Skip to content

[Gardening] Update the utils/backtrace-check script to use more modern Python formatting. #29424

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 63 additions & 37 deletions utils/backtrace-check
Original file line number Diff line number Diff line change
@@ -1,54 +1,82 @@
#!/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

"""
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 absolute_import, print_function, unicode_literals

import argparse
import re
import sys


def main():
# -----------------------------------------------------------------------------
# Constants

DESCRIPTION = """
Checks that a stacktrace dump follows canonical formatting.
"""

TARGET_PATTERN = re.compile(
r'(?P<index>\d+) +(?P<object>\S+) +(?P<address>0x[0-9a-fA-F]{16}) '
r'(?P<routine>[^+]+) [+] (?P<offset>\d+)')

RESULTS_FORMAT = """Stack Trace Entry:
\tIndex: '%(index)s'
\tObject File: '%(object)s'
\tAddress: '%(address)s'
\tRoutine: '%(routine)s'
\tOffset: '%(offset)s'
"""


# -----------------------------------------------------------------------------

def parse_args():
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description="""Checks that a stacktrace dump follows canonical
formatting.""")
description=DESCRIPTION)

parser.add_argument(
"-u", "--check-unavailable", action='store_true',
help="Checks if any symbols were unavailable")
args = parser.parse_args()
'-u', '--check-unavailable',
action='store_true',
help='Checks if any symbols were unavailable')

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+)")
return parser.parse_args()


def main():
args = parse_args()

lines = sys.stdin.readlines()

found_stack_trace_start = False
found_stack_trace_entry = False
for line in lines:
line = line.rstrip("\n")
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:":
if line == 'Current stack trace:':
assert(not found_stack_trace_start)
found_stack_trace_start = True
continue
Expand All @@ -59,21 +87,19 @@ formatting.""")
continue

# Ok, we are in the middle of matching a stack trace entry.
m = TARGET_RE.match(line)
matches = TARGET_PATTERN.match(line)

# If we fail to match, we have exited the stack trace entry region
if m is None:
if matches 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())
print(RESULTS_FORMAT.format(**matches.groupdict()))

# Check for unavailable symbols, if that was requested.
if args.check_unavailable:
assert("unavailable" not in m.group("routine"))
assert('unavailable' not in matches.group('routine'))

# Once we have processed all of the lines, make sure that we found at least
# one stack trace entry.
Expand Down