mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
73 lines
2.6 KiB
Swift
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
|
|
}
|
|
}
|