diff --git a/stdlib/public/Backtracing/BacktraceFormatter.swift b/stdlib/public/Backtracing/BacktraceFormatter.swift index 20b38de5398b1..9ac84850e1e13 100644 --- a/stdlib/public/Backtracing/BacktraceFormatter.swift +++ b/stdlib/public/Backtracing/BacktraceFormatter.swift @@ -654,7 +654,16 @@ public struct BacktraceFormatter { // sourceLocation.column is an index in UTF-8 code units in // `untabified`. We should point at the grapheme cluster that // contains that UTF-8 index. - let adjustedColumn = max(sourceLocation.column, 1) + let adjustedColumn: Int + if sourceLocation.column > 0 { + adjustedColumn = sourceLocation.column + } else { + if let ndx = code.firstIndex(where: { $0 != " " }) { + adjustedColumn = code.distance(from: code.startIndex, to: ndx) + 1 + } else { + adjustedColumn = 1 + } + } let utf8Ndx = untabified.utf8.index(untabified.utf8.startIndex, offsetBy: adjustedColumn, diff --git a/stdlib/public/Backtracing/FramePointerUnwinder.swift b/stdlib/public/Backtracing/FramePointerUnwinder.swift index d5cc7b25a61ea..d8232e9be58ee 100644 --- a/stdlib/public/Backtracing/FramePointerUnwinder.swift +++ b/stdlib/public/Backtracing/FramePointerUnwinder.swift @@ -16,10 +16,6 @@ import Swift -// @available(SwiftStdlib 5.1, *) -@_silgen_name("swift_task_getCurrent") -func _getCurrentAsyncTask() -> UnsafeRawPointer? - @_spi(Unwinders) public struct FramePointerUnwinder: Sequence, IteratorProtocol { public typealias Context = C @@ -47,7 +43,7 @@ public struct FramePointerUnwinder: Sequence, Itera #if (os(macOS) || os(iOS) || os(watchOS)) && (arch(arm64) || arch(arm64_32) || arch(x86_64)) // On Darwin, we borrow a bit of the frame pointer to indicate async // stack frames - return (storedFp & (1 << 60)) != 0 && _getCurrentAsyncTask() != nil + return (storedFp & (1 << 60)) != 0 #else return false #endif diff --git a/stdlib/public/Backtracing/SymbolicatedBacktrace.swift b/stdlib/public/Backtracing/SymbolicatedBacktrace.swift index 35c66bf3ca1e1..72d827c156744 100644 --- a/stdlib/public/Backtracing/SymbolicatedBacktrace.swift +++ b/stdlib/public/Backtracing/SymbolicatedBacktrace.swift @@ -148,11 +148,17 @@ public struct SymbolicatedBacktrace: CustomStringConvertible { if rawName == "start" && imageName == "dyld" { return true } - if let location = sourceLocation, - location.line == 0 && location.column == 0 { + if rawName.hasSuffix("5$mainyyFZ") + || rawName.hasSuffix("5$mainyyYaFZTQ0_") + || rawName == "_async_MainTQ0_" { + return true + } + if rawName == "__ZL23completeTaskWithClosurePN5swift12AsyncContextEPNS_10SwiftErrorE" && imageName == "libswift_Concurrency.dylib" { return true } - if rawName.hasSuffix("5$mainyyFZ") { + if let location = sourceLocation, + location.line == 0 && location.column == 0 + && !_swift_isThunkFunction(rawName) { return true } #endif diff --git a/test/Backtracing/CrashAsync.swift b/test/Backtracing/CrashAsync.swift new file mode 100644 index 0000000000000..45ad1fccf5da7 --- /dev/null +++ b/test/Backtracing/CrashAsync.swift @@ -0,0 +1,99 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -parse-as-library -Onone -g -o %t/CrashAsync +// RUN: %target-codesign %t/CrashAsync + +// Demangling is disabled for now because older macOS can't demangle async +// function names. We test demangling elsewhere, so this is no big deal. + +// RUN: (env SWIFT_BACKTRACE=enable=yes,demangle=no,cache=no %target-run %t/CrashAsync || true) | %FileCheck %s +// RUN: (env SWIFT_BACKTRACE=preset=friendly,enable=yes,demangle=no,cache=no %target-run %t/CrashAsync || true) | %FileCheck %s --check-prefix FRIENDLY + +// UNSUPPORTED: use_os_stdlib +// UNSUPPORTED: back_deployment_runtime +// REQUIRES: executable_test +// REQUIRES: backtracing +// REQUIRES: OS=macosx + +@available(SwiftStdlib 5.1, *) +func crash() { + let ptr = UnsafeMutablePointer(bitPattern: 4)! + ptr.pointee = 42 +} + +@available(SwiftStdlib 5.1, *) +func level(_ n: Int) async { + if n < 5 { + await level(n + 1) + } else { + crash() + } +} + +@available(SwiftStdlib 5.1, *) +@main +struct CrashAsync { + static func main() async { + await level(1) + } +} + +// CHECK: *** Program crashed: Bad pointer dereference at 0x{{0+}}4 *** + +// CHECK: Thread {{[0-9]+}} crashed: + +// CHECK: 0 0x{{[0-9a-f]+}} _$s10CrashAsync5crashyyF + {{[0-9]+}} in CrashAsync at {{.*}}/CrashAsync.swift:20:15 +// CHECK-NEXT: 1 [ra] 0x{{[0-9a-f]+}} _$s10CrashAsync5levelyySiYaFTY0_ + {{[0-9]+}} in CrashAsync at {{.*}}/CrashAsync.swift:28:5 +// CHECK-NEXT: 2 [async] 0x{{[0-9a-f]+}} _$s10CrashAsync5levelyySiYaFTQ1_ in CrashAsync at {{.*}}/CrashAsync.swift:26 +// CHECK-NEXT: 3 [async] 0x{{[0-9a-f]+}} _$s10CrashAsync5levelyySiYaFTQ1_ in CrashAsync at {{.*}}/CrashAsync.swift:26 +// CHECK-NEXT: 4 [async] 0x{{[0-9a-f]+}} _$s10CrashAsync5levelyySiYaFTQ1_ in CrashAsync at {{.*}}/CrashAsync.swift:26 +// CHECK-NEXT: 5 [async] 0x{{[0-9a-f]+}} _$s10CrashAsync5levelyySiYaFTQ1_ in CrashAsync at {{.*}}/CrashAsync.swift:26 +// CHECK-NEXT: 6 [async] 0x{{[0-9a-f]+}} _$s10CrashAsyncAAV4mainyyYaFZTQ0_ in CrashAsync at {{.*}}/CrashAsync.swift:36 +// CHECK-NEXT: 7 [async] [system] 0x{{[0-9a-f]+}} _$s10CrashAsyncAAV5$mainyyYaFZTQ0_ in CrashAsync at {{.*}}/ +// CHECK-NEXT: 8 [async] [system] 0x{{[0-9a-f]+}} _async_MainTQ0_ in CrashAsync at {{.*}}/ +// CHECK-NEXT: 9 [async] [thunk] 0x{{[0-9a-f]+}} _$sIetH_yts5Error_pIegHrzo_TRTQ0_ in CrashAsync at {{.*}}/ +// CHECK-NEXT: 10 [async] [thunk] 0x{{[0-9a-f]+}} _$sIetH_yts5Error_pIegHrzo_TRTATQ0_ in CrashAsync at {{.*}}/ +// CHECK-NEXT: 11 [async] [system] 0x{{[0-9a-f]+}} __ZL23completeTaskWithClosurePN5swift12AsyncContextEPNS_10SwiftErrorE in libswift_Concurrency.dylib at {{.*}}/Task.cpp:463 + +// FRIENDLY: *** Program crashed: Bad pointer dereference at 0x{{0+}}4 *** + +// FRIENDLY: Thread {{[0-9]+}} crashed: + +// FRIENDLY: 0 _$s10CrashAsync5crashyyF + {{[0-9]+}} in CrashAsync at {{.*}}CrashAsync.swift:20:15 + +// FRIENDLY: 18| func crash() { +// FRIENDLY-NEXT: 19| let ptr = UnsafeMutablePointer(bitPattern: 4)! +// FRIENDLY-NEXT: * 20| ptr.pointee = 42 +// FRIENDLY-NEXT: | ^ +// FRIENDLY-NEXT: 21| } +// FRIENDLY-NEXT: 22| + +// FRIENDLY: 1 _$s10CrashAsync5levelyySiYaFTY0_ + {{[0-9]+}} in CrashAsync at {{.*}}CrashAsync.swift:28:5 + +// FRIENDLY: 26| await level(n + 1) +// FRIENDLY-NEXT: 27| } else { +// FRIENDLY-NEXT: * 28| crash() +// FRIENDLY-NEXT: | ^ +// FRIENDLY-NEXT: 29| } +// FRIENDLY-NEXT: 30| } + +// FRIENDLY:2 _$s10CrashAsync5levelyySiYaFTQ1_ in CrashAsync at {{.*}}CrashAsync.swift:26 + +// FRIENDLY: 24| func level(_ n: Int) async { +// FRIENDLY-NEXT: 25| if n < 5 { +// FRIENDLY-NEXT: * 26| await level(n + 1) +// FRIENDLY-NEXT: | ^ +// FRIENDLY-NEXT: 27| } else { +// FRIENDLY-NEXT: 28| crash() + +// FRIENDLY: 3 _$s10CrashAsync5levelyySiYaFTQ1_ in CrashAsync at {{.*}}CrashAsync.swift:26 +// FRIENDLY: 4 _$s10CrashAsync5levelyySiYaFTQ1_ in CrashAsync at {{.*}}CrashAsync.swift:26 +// FRIENDLY: 5 _$s10CrashAsync5levelyySiYaFTQ1_ in CrashAsync at {{.*}}CrashAsync.swift:26 +// FRIENDLY: 6 _$s10CrashAsyncAAV4mainyyYaFZTQ0_ in CrashAsync at {{.*}}CrashAsync.swift:36 + +// FRIENDLY: 34| struct CrashAsync { +// FRIENDLY-NEXT: 35| static func main() async { +// FRIENDLY-NEXT: * 36| await level(1) +// FRIENDLY-NEXT: | ^ +// FRIENDLY-NEXT: 37| } +// FRIENDLY-NEXT: 38| } + diff --git a/test/Backtracing/CrashWithThunk.swift b/test/Backtracing/CrashWithThunk.swift index 741a44a1157b9..d448d970845e3 100644 --- a/test/Backtracing/CrashWithThunk.swift +++ b/test/Backtracing/CrashWithThunk.swift @@ -33,11 +33,11 @@ struct CrashWithThunk { // CHECK: Thread 0 crashed: -// CHECK: 0 0x{{[0-9a-f]+}} crash() + {{[0-9]+}} in CrashWithThunk at {{.*}}/CrashWithThunk.swift:20:15 -// CHECK-NEXT: 1 [ra] [thunk] [system] 0x{{[0-9a-f]+}} thunk for @escaping @callee_guaranteed () -> () + {{[0-9]+}} in CrashWithThunk at {{.*}}/Backtracing/ -// CHECK-NEXT: 2 [ra] 0x{{[0-9a-f]+}} static CrashWithThunk.main() + {{[0-9]+}} in CrashWithThunk at {{.*}}/CrashWithThunk.swift:28:9 -// CHECK-NEXT: 3 [ra] [system] 0x{{[0-9a-f]+}} static CrashWithThunk.$main() + {{[0-9]+}} in CrashWithThunk at {{.*}}/CrashWithThunk.swift:23:1 -// CHECK-NEXT: 4 [ra] [system] 0x{{[0-9a-f]+}} main + {{[0-9]+}} in CrashWithThunk at {{.*}}/CrashWithThunk.swift +// CHECK: 0 0x{{[0-9a-f]+}} crash() + {{[0-9]+}} in CrashWithThunk at {{.*}}/CrashWithThunk.swift:20:15 +// CHECK-NEXT: 1 [ra] [thunk] 0x{{[0-9a-f]+}} thunk for @escaping @callee_guaranteed () -> () + {{[0-9]+}} in CrashWithThunk at {{.*}}/Backtracing/ +// CHECK-NEXT: 2 [ra] 0x{{[0-9a-f]+}} static CrashWithThunk.main() + {{[0-9]+}} in CrashWithThunk at {{.*}}/CrashWithThunk.swift:28:9 +// CHECK-NEXT: 3 [ra] [system] 0x{{[0-9a-f]+}} static CrashWithThunk.$main() + {{[0-9]+}} in CrashWithThunk at {{.*}}/CrashWithThunk.swift:23:1 +// CHECK-NEXT: 4 [ra] [system] 0x{{[0-9a-f]+}} main + {{[0-9]+}} in CrashWithThunk at {{.*}}/CrashWithThunk.swift // CHECK: Registers: