Skip to content

Commit d711129

Browse files
authored
Merge pull request #71553 from al45tair/eng/PR-122302117-5.10
[Runtime] Add an option to produce non-symbolicated backtraces.
2 parents 63c8b55 + 8cd35f0 commit d711129

12 files changed

+458
-124
lines changed

docs/Backtracing.rst

+4
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ follows:
100100
| | | standard error instead of standard output. This |
101101
| | | may be useful in some CI systems. |
102102
+-----------------+---------+--------------------------------------------------+
103+
| symbolicate | full | Options are ``full``, ``fast``, or ``off``. |
104+
| | | Full means to look up source locations and |
105+
| | | inline frames. Fast just does symbol lookup. |
106+
+-----------------+---------+--------------------------------------------------+
103107
| swift-backtrace | | If specified, gives the full path to the |
104108
| | | swift-backtrace binary to use for crashes. |
105109
| | | Otherwise, Swift will locate the binary relative |

docs/contents.rst

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Contents
66
.. toctree::
77
:maxdepth: 1
88

9+
Backtracing
910
Generics
1011
StoredAndComputedVariables
1112
SIL

stdlib/public/Backtracing/Backtrace.swift

+12-5
Original file line numberDiff line numberDiff line change
@@ -613,20 +613,27 @@ public struct Backtrace: CustomStringConvertible, Sendable {
613613
/// running on, add virtual frames to show inline
614614
/// function calls.
615615
///
616+
/// @param showSourceLocation If `true`, look up the source location for
617+
/// each address.
618+
///
616619
/// @param useSymbolCache If the system we are on has a symbol cache,
617620
/// says whether or not to use it.
618621
///
619622
/// @returns A new `SymbolicatedBacktrace`.
620623
public func symbolicated(with images: [Image]? = nil,
621624
sharedCacheInfo: SharedCacheInfo? = nil,
622625
showInlineFrames: Bool = true,
626+
showSourceLocations: Bool = true,
623627
useSymbolCache: Bool = true)
624628
-> SymbolicatedBacktrace? {
625-
return SymbolicatedBacktrace.symbolicate(backtrace: self,
626-
images: images,
627-
sharedCacheInfo: sharedCacheInfo,
628-
showInlineFrames: showInlineFrames,
629-
useSymbolCache: useSymbolCache)
629+
return SymbolicatedBacktrace.symbolicate(
630+
backtrace: self,
631+
images: images,
632+
sharedCacheInfo: sharedCacheInfo,
633+
showInlineFrames: showInlineFrames,
634+
showSourceLocations: showSourceLocations,
635+
useSymbolCache: useSymbolCache
636+
)
630637
}
631638

632639
/// Provide a textual version of the backtrace.

stdlib/public/Backtracing/BacktraceFormatter.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -545,12 +545,12 @@ public struct BacktraceFormatter {
545545
if let index = index {
546546
columns.append(options._theme.frameIndex("\(index)"))
547547
}
548-
columns.append(options._theme.programCounter(pc))
549548
if options._showFrameAttributes {
550549
columns.append(attrs.map(
551550
options._theme.frameAttribute
552551
).joined(separator: " "))
553552
}
553+
columns.append(options._theme.programCounter(pc))
554554

555555
return columns
556556
}

stdlib/public/Backtracing/SymbolicatedBacktrace.swift

+57-31
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ public struct SymbolicatedBacktrace: CustomStringConvertible {
336336
with owner: CSSymbolOwnerRef,
337337
isInline: Bool,
338338
symbol: CSSymbolRef,
339-
sourceInfo: CSSourceInfoRef,
339+
sourceInfo: CSSourceInfoRef?,
340340
images: [Backtrace.Image]) -> Frame {
341341
if CSIsNull(symbol) {
342342
return Frame(captured: capturedFrame, symbol: nil)
@@ -349,7 +349,7 @@ public struct SymbolicatedBacktrace: CustomStringConvertible {
349349

350350
let location: SourceLocation?
351351

352-
if !CSIsNull(sourceInfo) {
352+
if let sourceInfo = sourceInfo, !CSIsNull(sourceInfo) {
353353
let path = CSSourceInfoGetPath(sourceInfo) ?? "<unknown>"
354354
let line = CSSourceInfoGetLineNumber(sourceInfo)
355355
let column = CSSourceInfoGetColumn(sourceInfo)
@@ -390,6 +390,7 @@ public struct SymbolicatedBacktrace: CustomStringConvertible {
390390
images: [Backtrace.Image]?,
391391
sharedCacheInfo: Backtrace.SharedCacheInfo?,
392392
showInlineFrames: Bool,
393+
showSourceLocations: Bool,
393394
useSymbolCache: Bool)
394395
-> SymbolicatedBacktrace? {
395396

@@ -449,7 +450,7 @@ public struct SymbolicatedBacktrace: CustomStringConvertible {
449450

450451
first = false
451452
}
452-
} else {
453+
} else if showSourceLocations {
453454
let symbol = CSSymbolOwnerGetSymbolWithAddress(owner, address)
454455
let sourceInfo = CSSymbolOwnerGetSourceInfoWithAddress(owner,
455456
address)
@@ -460,6 +461,15 @@ public struct SymbolicatedBacktrace: CustomStringConvertible {
460461
symbol: symbol,
461462
sourceInfo: sourceInfo,
462463
images: theImages))
464+
} else {
465+
let symbol = CSSymbolOwnerGetSymbolWithAddress(owner, address)
466+
467+
frames.append(buildFrame(from: frame,
468+
with: owner,
469+
isInline: false,
470+
symbol: symbol,
471+
sourceInfo: nil,
472+
images: theImages))
463473
}
464474
}
465475
}
@@ -500,21 +510,29 @@ public struct SymbolicatedBacktrace: CustomStringConvertible {
500510
}
501511

502512
if let theSymbol = elf32Image?.lookupSymbol(address: relativeAddress) {
503-
var location = try? elf32Image!.sourceLocation(for: relativeAddress)
513+
var location: SourceLocation?
504514

505-
for inline in elf32Image!.inlineCallSites(at: relativeAddress) {
506-
let fakeSymbol = Symbol(imageIndex: imageNdx,
507-
imageName: theImages[imageNdx].name,
508-
rawName: inline.rawName ?? "<unknown>",
509-
offset: 0,
510-
sourceLocation: location)
511-
frames.append(Frame(captured: frame,
512-
symbol: fakeSymbol,
513-
inlined: true))
514-
515-
location = SourceLocation(path: inline.filename,
516-
line: inline.line,
517-
column: inline.column)
515+
if showSourceLocations || showInlineFrames {
516+
location = try? elf32Image!.sourceLocation(for: relativeAddress)
517+
} else {
518+
location = nil
519+
}
520+
521+
if showInlineFrames {
522+
for inline in elf32Image!.inlineCallSites(at: relativeAddress) {
523+
let fakeSymbol = Symbol(imageIndex: imageNdx,
524+
imageName: theImages[imageNdx].name,
525+
rawName: inline.rawName ?? "<unknown>",
526+
offset: 0,
527+
sourceLocation: location)
528+
frames.append(Frame(captured: frame,
529+
symbol: fakeSymbol,
530+
inlined: true))
531+
532+
location = SourceLocation(path: inline.filename,
533+
line: inline.line,
534+
column: inline.column)
535+
}
518536
}
519537

520538
symbol = Symbol(imageIndex: imageNdx,
@@ -523,21 +541,29 @@ public struct SymbolicatedBacktrace: CustomStringConvertible {
523541
offset: theSymbol.offset,
524542
sourceLocation: location)
525543
} else if let theSymbol = elf64Image?.lookupSymbol(address: relativeAddress) {
526-
var location = try? elf64Image!.sourceLocation(for: relativeAddress)
544+
var location: SourceLocation?
527545

528-
for inline in elf64Image!.inlineCallSites(at: relativeAddress) {
529-
let fakeSymbol = Symbol(imageIndex: imageNdx,
530-
imageName: theImages[imageNdx].name,
531-
rawName: inline.rawName ?? "<unknown>",
532-
offset: 0,
533-
sourceLocation: location)
534-
frames.append(Frame(captured: frame,
535-
symbol: fakeSymbol,
536-
inlined: true))
537-
538-
location = SourceLocation(path: inline.filename,
539-
line: inline.line,
540-
column: inline.column)
546+
if showSourceLocations || showInlineFrames {
547+
location = try? elf64Image!.sourceLocation(for: relativeAddress)
548+
} else {
549+
location = nil
550+
}
551+
552+
if showInlineFrames {
553+
for inline in elf64Image!.inlineCallSites(at: relativeAddress) {
554+
let fakeSymbol = Symbol(imageIndex: imageNdx,
555+
imageName: theImages[imageNdx].name,
556+
rawName: inline.rawName ?? "<unknown>",
557+
offset: 0,
558+
sourceLocation: location)
559+
frames.append(Frame(captured: frame,
560+
symbol: fakeSymbol,
561+
inlined: true))
562+
563+
location = SourceLocation(path: inline.filename,
564+
line: inline.line,
565+
column: inline.column)
566+
}
541567
}
542568

543569
symbol = Symbol(imageIndex: imageNdx,

stdlib/public/libexec/swift-backtrace/TargetLinux.swift

+85-21
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,18 @@ import _Backtracing
2727

2828
@_implementationOnly import Runtime
2929

30+
enum SomeBacktrace {
31+
case raw(Backtrace)
32+
case symbolicated(SymbolicatedBacktrace)
33+
}
34+
3035
struct TargetThread {
3136
typealias ThreadID = pid_t
3237

3338
var id: ThreadID
3439
var context: HostContext?
3540
var name: String
36-
var backtrace: SymbolicatedBacktrace
41+
var backtrace: SomeBacktrace
3742
}
3843

3944
class Target {
@@ -105,7 +110,8 @@ class Target {
105110
return trimmed
106111
}
107112

108-
init(crashInfoAddr: UInt64, limit: Int?, top: Int, cache: Bool) {
113+
init(crashInfoAddr: UInt64, limit: Int?, top: Int, cache: Bool,
114+
symbolicate: SwiftBacktrace.Symbolication) {
109115
// fd #4 is reserved for the memory server
110116
let memserverFd: CInt = 4
111117

@@ -130,7 +136,8 @@ class Target {
130136

131137
do {
132138
try fetchThreads(threadListHead: Address(crashInfo.thread_list),
133-
limit: limit, top: top, cache: cache)
139+
limit: limit, top: top, cache: cache,
140+
symbolicate: symbolicate)
134141
} catch {
135142
print("swift-backtrace: failed to fetch thread information: \(error)")
136143
exit(1)
@@ -143,7 +150,8 @@ class Target {
143150
/// uninterruptible wait, we won't have a ucontext for it.
144151
func fetchThreads(
145152
threadListHead: Address,
146-
limit: Int?, top: Int, cache: Bool
153+
limit: Int?, top: Int, cache: Bool,
154+
symbolicate: SwiftBacktrace.Symbolication
147155
) throws {
148156
var next = threadListHead
149157

@@ -164,18 +172,46 @@ class Target {
164172
images: images,
165173
limit: limit,
166174
top: top)
167-
guard let symbolicated
168-
= backtrace.symbolicated(with: images,
169-
sharedCacheInfo: nil,
170-
useSymbolCache: cache) else {
171-
print("unable to symbolicate backtrace for thread \(t.tid)")
172-
exit(1)
175+
176+
let shouldSymbolicate: Bool
177+
let showInlineFrames: Bool
178+
let showSourceLocations: Bool
179+
switch symbolicate {
180+
case .off:
181+
shouldSymbolicate = false
182+
showInlineFrames = false
183+
showSourceLocations = false
184+
case .fast:
185+
shouldSymbolicate = true
186+
showInlineFrames = false
187+
showSourceLocations = false
188+
case .full:
189+
shouldSymbolicate = true
190+
showInlineFrames = true
191+
showSourceLocations = true
173192
}
174193

175-
threads.append(TargetThread(id: TargetThread.ThreadID(t.tid),
176-
context: context,
177-
name: getThreadName(tid: t.tid),
178-
backtrace: symbolicated))
194+
if shouldSymbolicate {
195+
guard let symbolicated
196+
= backtrace.symbolicated(with: images,
197+
sharedCacheInfo: nil,
198+
showInlineFrames: showInlineFrames,
199+
showSourceLocations: showSourceLocations,
200+
useSymbolCache: cache) else {
201+
print("unable to symbolicate backtrace for thread \(t.tid)")
202+
exit(1)
203+
}
204+
205+
threads.append(TargetThread(id: TargetThread.ThreadID(t.tid),
206+
context: context,
207+
name: getThreadName(tid: t.tid),
208+
backtrace: .symbolicated(symbolicated)))
209+
} else {
210+
threads.append(TargetThread(id: TargetThread.ThreadID(t.tid),
211+
context: context,
212+
name: getThreadName(tid: t.tid),
213+
backtrace: .raw(backtrace)))
214+
}
179215
}
180216

181217
// Sort the threads by thread ID; the main thread always sorts
@@ -193,7 +229,10 @@ class Target {
193229
}
194230
}
195231

196-
func redoBacktraces(limit: Int?, top: Int, cache: Bool) {
232+
func redoBacktraces(
233+
limit: Int?, top: Int, cache: Bool,
234+
symbolicate: SwiftBacktrace.Symbolication
235+
) {
197236
for (ndx, thread) in threads.enumerated() {
198237
guard let context = thread.context else {
199238
continue
@@ -208,14 +247,39 @@ class Target {
208247
continue
209248
}
210249

211-
guard let symbolicated = backtrace.symbolicated(with: images,
212-
sharedCacheInfo: nil,
213-
useSymbolCache: cache) else {
214-
print("unable to symbolicate backtrace from context for thread \(ndx)")
215-
continue
250+
let shouldSymbolicate: Bool
251+
let showInlineFrames: Bool
252+
let showSourceLocations: Bool
253+
switch symbolicate {
254+
case .off:
255+
shouldSymbolicate = false
256+
showInlineFrames = false
257+
showSourceLocations = false
258+
case .fast:
259+
shouldSymbolicate = true
260+
showInlineFrames = false
261+
showSourceLocations = false
262+
case .full:
263+
shouldSymbolicate = true
264+
showInlineFrames = true
265+
showSourceLocations = true
216266
}
217267

218-
threads[ndx].backtrace = symbolicated
268+
if shouldSymbolicate {
269+
guard let symbolicated = backtrace.symbolicated(
270+
with: images,
271+
sharedCacheInfo: nil,
272+
showInlineFrames: showInlineFrames,
273+
showSourceLocations: showSourceLocations,
274+
useSymbolCache: cache) else {
275+
print("unable to symbolicate backtrace from context for thread \(ndx)")
276+
continue
277+
}
278+
279+
threads[ndx].backtrace = .symbolicated(symbolicated)
280+
} else {
281+
threads[ndx].backtrace = .raw(backtrace)
282+
}
219283
}
220284
}
221285

0 commit comments

Comments
 (0)