Skip to content

Commit 534d3c3

Browse files
committed
[SE-0419] Tweak proposal slightly.
Added an `ImageMap` type to hold the list of loaded images. This is neater and allows for some optimizations as well as make it easier to support `Codable` for `Backtrace`. This also removes the `captureImages()` API in favour of `ImageMap.capture()`, which is more natural. Also exposed the ability to construct a `Backtrace.Address` from a `FixedWidthInteger`, write-protected `Backtrace.architecture`, and switch `SymbolicatedBacktrace` back to an explicit `Array` of `Frame`s as we aren't trying to minimise space for the symbolicated version.
1 parent 9d3bd3d commit 534d3c3

File tree

1 file changed

+50
-18
lines changed

1 file changed

+50
-18
lines changed

proposals/0419-backtrace-api.md

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ public struct Backtrace: CustomStringConvertible, Codable, Sendable {
180180
}
181181

182182
/// The architecture of the process to which this backtrace refers.
183-
public var architecture: String
183+
public var architecture: String { get }
184184

185185
/// A `Sequence` of captured frame information.
186186
///
@@ -194,8 +194,8 @@ public struct Backtrace: CustomStringConvertible, Codable, Sendable {
194194
/// Some backtracing algorithms may require this information, in which case
195195
/// it will be filled in by the `capture()` method. Other algorithms may
196196
/// not, in which case it will be `nil` and you can capture an image list
197-
/// separately yourself using `captureImages()`.
198-
public var images: [Image]?
197+
/// separately yourself using `ImageMap.capture()`.
198+
public var images: ImageMap?
199199

200200
/// Capture a backtrace from the current program location.
201201
///
@@ -222,12 +222,6 @@ public struct Backtrace: CustomStringConvertible, Codable, Sendable {
222222
offset: Int = 0,
223223
top: Int = 16) throws -> Backtrace
224224

225-
/// Capture a list of the images currently mapped into the calling
226-
/// process.
227-
///
228-
/// @returns A list of `Image`s.
229-
public static func captureImages() -> [Image]
230-
231225
/// Specifies options for the `symbolicated` method.
232226
public struct SymbolicationOptions: OptionSet {
233227
public let rawValue: Int
@@ -259,7 +253,7 @@ public struct Backtrace: CustomStringConvertible, Codable, Sendable {
259253
/// @param options Symbolication options; see `SymbolicationOptions`.
260254
///
261255
/// @returns A new `SymbolicatedBacktrace`.
262-
public func symbolicated(with images: [Image]? = nil,
256+
public func symbolicated(with images: ImageMap? = nil,
263257
options: SymbolicationOptions = .default)
264258
-> SymbolicatedBacktrace?
265259

@@ -283,6 +277,43 @@ extension FixedWidthInteger {
283277
}
284278
```
285279

280+
We also allow conversion of a `FixedWidthInteger` to an address:
281+
282+
```swift
283+
extension Backtrace.Address {
284+
/// Convert from a FixedWidthInteger.
285+
///
286+
/// This initializer will return nil if the address width is not one that is
287+
/// currently supported by `Backtrace.Address`.
288+
///
289+
/// @param value The value to convert.
290+
public init?<T: FixedWidthInteger>(_ value: T)
291+
}
292+
```
293+
294+
The `ImageMap` type represents a captured list of loaded images, and
295+
implements the `Collection` protocol so can be indexed like an array:
296+
297+
```swift
298+
public struct ImageMap: Collection, Sendable, Hashable, CustomStringConvertible {
299+
300+
/// Capture the image map for the current process.
301+
public static func capture() -> ImageMap
302+
303+
/// The name of the platform that captured this image map.
304+
public private(set) var platform: String
305+
306+
/// Look-up an image by address.
307+
public func indexOfImage(at address: Backtrace.Address) -> Int?
308+
309+
}
310+
```
311+
312+
The `platform` string starts with a token identifying the operating
313+
system (e.g. `macOS`, `iOS`, `tvOS`, `watchOS`, `visionOS`, `Linux`,
314+
`Windows`) and may contain additional platform-specific version
315+
information thereafter.
316+
286317
_Symbolication_, by which we mean the process of looking up the symbols
287318
associated with addresses in a backtrace, is in general an expensive
288319
process, and for efficiency reasons is normally performed for a backtrace
@@ -385,10 +416,10 @@ public struct SymbolicatedBacktrace: CustomStringConvertible, Codable, Sendable
385416
}
386417

387418
/// A list of captured frame information.
388-
public var frames: some Sequence<Frame> { get }
419+
public var frames: [Frame] { get }
389420

390421
/// A list of images found in the process.
391-
public var images: [Backtrace.Image]
422+
public var images: ImageMap { get }
392423

393424
/// True if this backtrace is a Swift runtime failure.
394425
public var isSwiftRuntimeFailure: Bool { get }
@@ -451,12 +482,13 @@ of existentials; or it could have been a generic parameter, but doing
451482
that makes it difficult to cope with a backtrace unless you already
452483
know what kind of addresses it contains at compile time.
453484

454-
The `frames` member variables could have been arrays, but implementing
455-
them instead as a sequence means that we have the flexibility to use
456-
a different backing store where doing so makes sense. An example where
457-
we might want that is where we're capturing very large numbers of
458-
backtraces, in which case doing some kind of delta compression on the
459-
frame addresses might enable us to save significant amounts of memory.
485+
The `frames` member variable on `Backtrace` could have been an array,
486+
but implementing it instead as a sequence means that we have the
487+
flexibility to use a different backing store where doing so makes
488+
sense. An example where we might want that is where we're capturing
489+
very large numbers of backtraces, in which case doing some kind of
490+
delta compression on the frame addresses might enable us to save
491+
significant amounts of memory.
460492

461493
Some desirable features are intentionally left out of this proposal;
462494
the intent is that while some of these may even be implemented, they

0 commit comments

Comments
 (0)