[linux] swift-inspect support for Linux

This commit is contained in:
Andrew Rogers
2024-12-03 10:22:05 -08:00
parent 9e7fa1a023
commit 2ee5d15886
19 changed files with 1129 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 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 FileManager.default.fileExists(atPath: linkMapEntry.moduleName) else { continue }
let elfFile = try ElfFile(filePath: linkMapEntry.moduleName)
let symbolMap = try elfFile.loadSymbols(baseAddress: linkMapEntry.baseAddress)
symbolLookup[linkMapEntry.moduleName] = symbolMap
}
self.symbolLookup = symbolLookup
}
// find the address range for the requetsed 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 {
assert(address >= entry.start)
assert(address < entry.end)
return entry
}
}
return nil
}
}