Files
swift-mirror/tools/swift-inspect/Sources/SwiftInspectLinux/SymbolCache.swift
Andrew Rogers b7dff4232e PR feedback
2024-12-16 11:41:00 -08:00

73 lines
2.6 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2024 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
//
//===----------------------------------------------------------------------===//
import Foundation
import LinuxSystemHeaders
public class SymbolCache {
public typealias SymbolRange = (start: UInt64, end: UInt64)
public typealias SymbolInfo = (start: UInt64, end: UInt64, module: String, name: String)
public typealias SymbolLookup = [String: [String: SymbolRange]]
public let symbolLookup: SymbolLookup
let linkMap: LinkMap
// an array of all symbols sorted by their start address
lazy var sortedAddressLookup: [SymbolInfo] = {
var addressLookup: [SymbolInfo] = []
for (module, symbols) in self.symbolLookup {
for (name, (start, end)) in symbols {
addressLookup.append((start: start, end: end, module: module, name: name))
}
}
addressLookup.sort { $0.start < $1.start }
return addressLookup
}()
public init(for process: Process) throws {
self.linkMap = try LinkMap(for: process)
var symbolLookup: SymbolLookup = [:]
for linkMapEntry in linkMap.entries {
guard let elfFile = try? ElfFile(filePath: linkMapEntry.moduleName) else { continue }
let symbolMap = try elfFile.loadSymbols(baseAddress: linkMapEntry.baseAddress)
symbolLookup[linkMapEntry.moduleName] = symbolMap
}
self.symbolLookup = symbolLookup
}
// find the address range for the requested symbol
public func address(of symbol: String) -> SymbolRange? {
for (_, symbols) in symbolLookup { if let range = symbols[symbol] { return range } }
return nil
}
// find and return symbol that contains the specified address
public func symbol(for address: UInt64) -> SymbolInfo? {
var lowerBound = 0
var upperBound = self.sortedAddressLookup.count
while lowerBound < upperBound {
let currentIndex = (lowerBound + upperBound) / 2
let entry = self.sortedAddressLookup[currentIndex]
if entry.start > address {
upperBound = currentIndex
} else if entry.end <= address {
lowerBound = currentIndex + 1
} else {
precondition(address >= entry.start)
precondition(address < entry.end)
return entry
}
}
return nil
}
}