Skip to content

Commit 1d05e33

Browse files
committed
[Linux] Force the inclusion of the backtracing code when static linking.
When we're statically linking the standard library, we need to force the inclusion of the backtracing code in the runtime, otherwise we don't get on-crash backtraces. Also, add a test to make sure that this works. rdar://115774613
1 parent 1321678 commit 1d05e33

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-0
lines changed

stdlib/public/runtime/SwiftRT-ELF-WASM.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "ImageInspectionCommon.h"
1414
#include "swift/shims/MetadataSections.h"
15+
#include "swift/Runtime/Backtrace.h"
1516

1617
#include <cstddef>
1718
#include <new>
@@ -24,6 +25,11 @@ extern "C" const char __dso_handle[];
2425
static constexpr const void *__dso_handle = nullptr;
2526
#endif
2627

28+
// Drag in a symbol from the backtracer, to force the static linker to include
29+
// the code.
30+
static const void *__backtraceRef __attribute__((used))
31+
= (const void *)swift::runtime::backtrace::_swift_backtrace_isThunkFunction;
32+
2733
// Create empty sections to ensure that the start/stop symbols are synthesized
2834
// by the linker. Otherwise, we may end up with undefined symbol references as
2935
// the linker table section was never constructed.

test/Backtracing/CrashStatic.swift

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift %s -parse-as-library %import-libdispatch -Onone -static-stdlib -g -o %t/CrashStatic
3+
// RUN: %target-codesign %t/CrashStatic
4+
// RUN: (env SWIFT_BACKTRACE=enable=yes,cache=no,swift-backtrace=%backtracer %target-run %t/CrashStatic 2>&1 || true) | %FileCheck %s
5+
6+
// UNSUPPORTED: use_os_stdlib
7+
// UNSUPPORTED: back_deployment_runtime
8+
// UNSUPPORTED: asan
9+
// REQUIRES: executable_test
10+
// REQUIRES: backtracing
11+
// REQUIRES: static_stdlib
12+
// REQUIRES: OS=linux-gnu
13+
14+
func level1() {
15+
level2()
16+
}
17+
18+
func level2() {
19+
level3()
20+
}
21+
22+
func level3() {
23+
level4()
24+
}
25+
26+
func level4() {
27+
level5()
28+
}
29+
30+
func level5() {
31+
print("About to crash")
32+
let ptr = UnsafeMutablePointer<Int>(bitPattern: 4)!
33+
ptr.pointee = 42
34+
}
35+
36+
@main
37+
struct CrashStatic {
38+
static func main() {
39+
level1()
40+
}
41+
}
42+
43+
// CHECK: *** Program crashed: Bad pointer dereference at 0x{{0+}}4 ***
44+
45+
// CHECK: Thread 0 {{(".*" )?}}crashed:
46+
47+
// CHECK: 0 0x{{[0-9a-f]+}} level5() + {{[0-9]+}} in CrashStatic at {{.*}}/CrashStatic.swift:33:15
48+
// CHECK-NEXT: 1 [ra] 0x{{[0-9a-f]+}} level4() + {{[0-9]+}} in CrashStatic at {{.*}}/CrashStatic.swift:27:3
49+
// CHECK-NEXT: 2 [ra] 0x{{[0-9a-f]+}} level3() + {{[0-9]+}} in CrashStatic at {{.*}}/CrashStatic.swift:23:3
50+
// CHECK-NEXT: 3 [ra] 0x{{[0-9a-f]+}} level2() + {{[0-9]+}} in CrashStatic at {{.*}}/CrashStatic.swift:19:3
51+
// CHECK-NEXT: 4 [ra] 0x{{[0-9a-f]+}} level1() + {{[0-9]+}} in CrashStatic at {{.*}}/CrashStatic.swift:15:3
52+
// CHECK-NEXT: 5 [ra] 0x{{[0-9a-f]+}} static CrashStatic.main() + {{[0-9]+}} in CrashStatic at {{.*}}/CrashStatic.swift:39:5
53+
// CHECK-NEXT: 6 [ra] [system] 0x{{[0-9a-f]+}} static CrashStatic.$main() + {{[0-9]+}} in CrashStatic at {{.*}}/<compiler-generated>
54+
// CHECK-NEXT: 7 [ra] 0x{{[0-9a-f]+}} main + {{[0-9]+}} in CrashStatic at {{.*}}/CrashStatic.swift
55+
56+
// CHECK: Registers:
57+
58+
// CHECK: Images ({{[0-9]+}} omitted):
59+
60+
// CHECK: {{0x[0-9a-f]+}}–{{0x[0-9a-f]+}}{{ +}}{{([0-9a-f]+|<no build ID>)}}{{ +}}CrashStatic{{ +}}{{.*}}/CrashStatic

test/lit.cfg

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ config.scale_test = make_path(config.swift_utils, 'scale-test')
354354
config.PathSanitizingFileCheck = make_path(config.swift_utils, 'PathSanitizingFileCheck')
355355
config.swift_bin_dir = make_path(config.swift, '..', '..', 'bin')
356356
config.swift_lib_dir = make_path(config.swift, '..', '..', 'lib')
357+
config.swift_libexec_dir = make_path(config.swift, '..', '..', 'libexec')
357358
config.swift_share_dir = make_path(config.swift, '..', '..', 'share')
358359
config.round_trip_syntax_test = make_path(config.swift_utils, 'round-trip-syntax-test')
359360
config.refactor_check_compiles = make_path(config.swift_utils, 'refactor-check-compiles.py')
@@ -588,6 +589,7 @@ else:
588589
config.substitutions.append( ('%llvm_obj_root', config.llvm_obj_root) )
589590
config.substitutions.append( ('%swift-bin-dir', config.swift_bin_dir) )
590591
config.substitutions.append( ('%swift-lib-dir', config.swift_lib_dir) )
592+
config.substitutions.append( ('%swift-libexec-dir', config.swift_lib_dir) )
591593
config.substitutions.append( ('%swift-share-dir', config.swift_share_dir) )
592594
config.substitutions.append( ('%swift-plugin-dir', config.swift_plugin_dir) )
593595
config.substitutions.append( ('%llvm_src_root', config.llvm_src_root) )
@@ -1996,6 +1998,10 @@ if run_vendor == 'apple':
19961998
config.available_features.add('back_deploy_concurrency')
19971999
concurrency_back_deploy_path = os.path.join(os.path.dirname(swift_obj_root), os.path.basename(swift_obj_root).replace("swift-", "backdeployconcurrency-"), 'lib', 'swift-5.5', xcrun_sdk_name)
19982000

2001+
backtracer_path = make_path(config.swift_libexec_dir, 'swift',
2002+
config.target_sdk_name, 'swift-backtrace')
2003+
config.substitutions.append(('%backtracer', backtracer_path))
2004+
19992005
def os_stdlib_paths():
20002006
if run_vendor == 'apple':
20012007
if run_os == 'maccatalyst':

0 commit comments

Comments
 (0)