Files
swift-mirror/stdlib/public/RuntimeModule/SymbolLocator.swift
Carl Peto 0d542c57e3 [Windows] [Runtime] Fix import-ability of Runtime module (#90021)
Fixes #90019

Also added in more debug into the backtracer when DEBUG_BACKTRACING is
enabled.
2026-06-24 09:37:16 +01:00

132 lines
3.6 KiB
Swift

//===--- SymbolLocator.swift - Symbol file finding for Swift --------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2026 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Defines a protocol for a symbol locator that, when handed an image, can
// determine where the symbols for that image might be located.
//
//===----------------------------------------------------------------------===//
import Swift
@_implementationOnly import BacktracingImpl.Runtime
@_spi(SymbolLocation)
public struct SymbolLocationSymbol: Sendable, Hashable, Equatable {
var name: String
var offset: Int
var size: Int?
}
@_spi(SymbolLocation)
public struct SymbolLocationCallSiteInfo: Sendable, Hashable, Equatable {
var rawName: String?
var name: String?
var location: SymbolicatedBacktrace.SourceLocation
}
/// A `SymbolSource` is a place where we can fetch information about symbols.
/// It *may* be an image of some sort, or it could be some other kind of
/// thing (e.g. for Windows binaries, a PDB file).
@_spi(SymbolLocation)
public protocol SymbolSource {
typealias Address = UInt64
typealias Symbol = SymbolLocationSymbol
typealias CallSiteInfo = SymbolLocationCallSiteInfo
typealias SourceLocation = SymbolicatedBacktrace.SourceLocation
func lookupSymbol(address: Address) -> Symbol?
func sourceLocation(for address: Address) -> SourceLocation?
func inlineCallSites(at address: Address) -> Array<CallSiteInfo>
}
@_spi(SymbolLocation)
public protocol SymbolLocator {
typealias Image = SymbolLoader.Image
typealias ImageFormat = SymbolLoader.ImageFormat
func find(image: any Image) -> String?
func findSymbols(for image: any Image) -> (any SymbolSource)?
func findSymbols(for image: any Image,
format: ImageFormat) -> (any SymbolSource)?
}
@_spi(Symbolication)
extension SymbolLocator {
public func findSymbols(for image: any Image) -> (any SymbolSource)? {
return findSymbols(for: image, format: .auto)
}
}
@_spi(SymbolLocation)
extension Backtrace.Image: SymbolLocator.Image {
public var uuid: [UInt8]? { uniqueID }
public var age: UInt32? { nil }
}
@_spi(SymbolLocation)
public struct SymbolLoader {
public protocol Image {
var name: String? { get }
var path: String? { get }
var uuid: [UInt8]? { get }
var age: UInt32? { get }
}
public enum ImageFormat {
case auto
case elf
case peCoff
}
func loadSymbols(for image: any Image,
from path: String) -> (any SymbolSource)? {
let pdbCache = PDBCache.threadLocal
if let pdbFile = pdbCache.lookup(path: path) {
if pdbFile.signature == image.uuid && pdbFile.age == image.age {
return pdbFile
}
}
let elfCache = ElfImageCache.threadLocal
if let result = elfCache.lookup(path: path) {
switch result {
case let .elf32Image(elfImage):
if let uuid = image.uuid, uuid != elfImage.uuid {
return nil
}
return elfImage
case let .elf64Image(elfImage):
if let uuid = image.uuid, uuid != elfImage.uuid {
return nil
}
return elfImage
}
}
let peCache = PeImageCache.threadLocal
if let coffImage = peCache.lookup(path: path) {
if coffImage.getDwarfSection(.debugLine) != nil {
return coffImage
}
}
return nil
}
}