Skip to content

Commit 4ea0d20

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 666ab9f commit 4ea0d20

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-0
lines changed

stdlib/public/runtime/SwiftRT-ELF.cpp

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

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

1617
#include <cstddef>
1718
#include <new>
1819

1920
extern "C" const char __dso_handle[];
2021

22+
// Drag in a symbol from the backtracer, to force the static linker to include
23+
// the code.
24+
static const void *__backtraceRef __attribute__((used))
25+
= (const void *)swift::runtime::backtrace::_swift_backtrace_isThunkFunction;
26+
2127
// Create empty sections to ensure that the start/stop symbols are synthesized
2228
// by the linker. Otherwise, we may end up with undefined symbol references as
2329
// 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
@@ -352,6 +352,7 @@ config.rth = make_path(config.swift_utils, 'rth') # Resilience test helper
352352
config.scale_test = make_path(config.swift_utils, 'scale-test')
353353
config.PathSanitizingFileCheck = make_path(config.swift_utils, 'PathSanitizingFileCheck')
354354
config.swift_lib_dir = make_path(config.swift, '..', '..', 'lib')
355+
config.swift_libexec_dir = make_path(config.swift, '..', '..', 'libexec')
355356
config.round_trip_syntax_test = make_path(config.swift_utils, 'round-trip-syntax-test')
356357
config.refactor_check_compiles = make_path(config.swift_utils, 'refactor-check-compiles.py')
357358

@@ -580,6 +581,7 @@ else:
580581

581582
config.substitutions.append( ('%llvm_obj_root', config.llvm_obj_root) )
582583
config.substitutions.append( ('%swift-lib-dir', config.swift_lib_dir) )
584+
config.substitutions.append( ('%swift-libexec-dir', config.swift_lib_dir) )
583585
config.substitutions.append( ('%swift-plugin-dir', config.swift_plugin_dir) )
584586
config.substitutions.append( ('%llvm_src_root', config.llvm_src_root) )
585587
config.substitutions.append( ('%swift_obj_root', config.swift_obj_root) )
@@ -1980,6 +1982,10 @@ if run_vendor == 'apple':
19801982
config.available_features.add('back_deploy_concurrency')
19811983
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)
19821984

1985+
backtracer_path = make_path(config.swift_libexec_dir, 'swift',
1986+
config.target_sdk_name, 'swift-backtrace')
1987+
config.substitutions.append(('%backtracer', backtracer_path))
1988+
19831989
def os_stdlib_paths():
19841990
if run_vendor == 'apple':
19851991
if run_os == 'maccatalyst':

0 commit comments

Comments
 (0)