From d10146592d6188c5526ca51d994930381d9c6c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Grzegorz=20Mi=C5=82o=C5=9B?= Date: Thu, 8 Sep 2016 14:10:02 +0100 Subject: [PATCH] Review comments. Round 5. Integration test for symbolicate-linux-fatal. --- test/Runtime/linux-fatal-backtrace.swift | 23 ++++++ test/lit.site.cfg.in | 9 ++- utils/backtrace-check | 96 ++++++++++++++---------- utils/build-script-impl | 21 ++++++ utils/symbolicate-linux-fatal | 38 ++++++---- validation-test/lit.site.cfg.in | 2 - 6 files changed, 131 insertions(+), 58 deletions(-) create mode 100644 test/Runtime/linux-fatal-backtrace.swift diff --git a/test/Runtime/linux-fatal-backtrace.swift b/test/Runtime/linux-fatal-backtrace.swift new file mode 100644 index 0000000000000..c569d7c82fe73 --- /dev/null +++ b/test/Runtime/linux-fatal-backtrace.swift @@ -0,0 +1,23 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: %target-build-swift %s -o %t/a.out +// RUN: not --crash %t/a.out 2>&1 | PYTHONPATH=%lldb-python-path %utils/symbolicate-linux-fatal %t/a.out - | %utils/backtrace-check -u + +// REQUIRES: executable_test +// REQUIRES: OS=linux-gnu +// REQUIRES: lldb + +// Backtraces are not emitted when optimizations are enabled. This test can not +// run when optimizations are enabled. +// REQUIRES: swift_test_mode_optimize_none + +func funcB() { + fatalError("linux-fatal-backtrace"); +} + +func funcA() { + funcB(); +} + +print("bla") +funcA() diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in index 91c985a83cc04..f3f1fa8b0f0de 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -14,8 +14,6 @@ import os import platform import sys -## Autogenerated by Swift configuration. -# Do not edit! config.llvm_src_root = "@LLVM_MAIN_SRC_DIR@" config.llvm_obj_root = "@LLVM_BINARY_DIR@" config.llvm_tools_dir = "@LLVM_TOOLS_DIR@" @@ -76,6 +74,13 @@ if "@CMAKE_GENERATOR@" == "Xcode": config.environment['PATH'] = \ os.path.pathsep.join((xcode_bin_dir, config.environment['PATH'])) +if "@LLDB_ENABLE@" == "TRUE": + config.available_features.add('lldb') + for root, dirs, files in os.walk("@LLDB_BUILD_DIR@"): + if root.endswith("site-packages"): + config.substitutions.append(('%lldb-python-path', root)) + break + # Let the main config do the real work. if config.test_exec_root is None: config.test_exec_root = os.path.dirname(os.path.realpath(__file__)) diff --git a/utils/backtrace-check b/utils/backtrace-check index a7bd0bbdef969..9072b416a27ae 100755 --- a/utils/backtrace-check +++ b/utils/backtrace-check @@ -18,44 +18,64 @@ # 11 libswiftCore.dylib 0x000000000dce84d0l _fatalErrorMessage(StaticString, # StaticString, StaticString, UInt, flags : UInt32) -> () + 444 +import argparse import re import sys -TARGET_RE = re.compile( - "(?P\d+) +(?P\S+) +(?P
0x[0-9a-fA-F]{16}) " - "(?P[^+]+) [+] (?P\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()) - -# Once we have processed all of the lines, make sure that we found at least one -# stack trace entry. -assert(found_stack_trace_entry) + +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\d+) +(?P\S+) +(?P
0x[0-9a-fA-F]{16}) " + "(?P[^+]+) [+] (?P\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() diff --git a/utils/build-script-impl b/utils/build-script-impl index 779893aa15fd1..9301acc8f61e5 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -1240,6 +1240,18 @@ if [[ ! "${SKIP_BUILD_SWIFTPM}" ]] ; then PRODUCTS=("${PRODUCTS[@]}" swiftpm) fi +# Checks if a given product is enabled (i.e. part of $PRODUCS array) +function contains_product() { + local current_product + for current_product in "$PRODUCTS"; do + if [[ "$current_product" == "$1" ]]; then + return 1 + fi + done + return 0 +} + + # get_host_specific_variable(host, name) # # Get the value of a host-specific variable expected to have been passed by the @@ -2039,6 +2051,15 @@ for host in "${ALL_HOSTS[@]}"; do ) fi + if contains_product "lldb" ; then + lldb_build_dir=$(build_directory ${host} lldb) + cmake_options=( + "${cmake_options[@]}" + -DLLDB_ENABLE:BOOL=TRUE + -DLLDB_BUILD_DIR:STRING="${lldb_build_dir}" + ) + fi + build_targets=(all "${SWIFT_STDLIB_TARGETS[@]}") if [[ $(true_false "${build_perf_testsuite_this_time}") == "TRUE" ]]; then native_swift_tools_path="$(build_directory_bin ${LOCAL_HOST} swift)" diff --git a/utils/symbolicate-linux-fatal b/utils/symbolicate-linux-fatal index f8f33d53b5635..9f2893b491539 100755 --- a/utils/symbolicate-linux-fatal +++ b/utils/symbolicate-linux-fatal @@ -26,6 +26,7 @@ from __future__ import print_function import argparse import subprocess +import sys import lldb @@ -84,16 +85,19 @@ def process_stack(binary, dyn_libs, stack): memmap[dynlib_path] = dynlib_baseaddr else: framePC = int(stack_tokens[2], 16) + int(stack_tokens[-1], 10) - full_stack.append({"line": line, "framePC": framePC}) + full_stack.append( + {"line": line, "framePC": framePC, "dynlib_fname": dynlib_fname}) lldb_target = create_lldb_target(binary, memmap) frame_idx = 0 for frame in full_stack: use_orig_line = True frame_addr = frame["framePC"] + dynlib_fname = frame["dynlib_fname"] so_addr = lldb_target.ResolveLoadAddress(frame_addr-1) sym_ctx = so_addr.GetSymbolContext(lldb.eSymbolContextEverything) - frame_fragment = "{0: <4d} 0x{1:016x}".format(frame_idx, frame_addr) + frame_fragment = "{0: <4d} {1:20s} 0x{2:016x}".format( + frame_idx, dynlib_fname, frame_addr) symbol = sym_ctx.GetSymbol() if symbol.IsValid(): symbol_base = symbol.GetStartAddress().GetLoadAddress(lldb_target) @@ -127,7 +131,10 @@ def main(): args = parser.parse_args() binary = args.binary - logfile = args.log + if args.log == "-": + logfile = sys.stdin + else: + logfile = open(args.log, 'rU') lddoutput = subprocess.check_output( ['ldd', binary], stderr=subprocess.STDOUT) @@ -136,19 +143,18 @@ def main(): instack = False stackidx = 0 stack = [] - with open(logfile, 'rU') as f: - for line in f: - if instack and line.startswith(str(stackidx)): - stack.append(line) - stackidx = stackidx + 1 - else: - instack = False - stackidx = 0 - process_stack(binary, dyn_libs, stack) - stack = [] - print(line.rstrip()) - if line.startswith("Current stack trace:"): - instack = True + for line in logfile: + if instack and line.startswith(str(stackidx)): + stack.append(line) + stackidx = stackidx + 1 + else: + instack = False + stackidx = 0 + process_stack(binary, dyn_libs, stack) + stack = [] + print(line.rstrip()) + if line.startswith("Current stack trace:"): + instack = True process_stack(binary, dyn_libs, stack) diff --git a/validation-test/lit.site.cfg.in b/validation-test/lit.site.cfg.in index 32ef45118657f..2ce21ee587da3 100644 --- a/validation-test/lit.site.cfg.in +++ b/validation-test/lit.site.cfg.in @@ -13,8 +13,6 @@ import sys import platform -## Autogenerated by Swift configuration. -# Do not edit! config.llvm_src_root = "@LLVM_MAIN_SRC_DIR@" config.llvm_obj_root = "@LLVM_BINARY_DIR@" config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"