//===--- 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 internal 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 } @_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 } }