mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Backtracing] Add ImageMap instead of just using an Array.
We want to be able to efficiently serialise lists of images, and to do so it makes most sense to create a separate `ImageMap` type. This also provides a useful place to put methods to e.g. find an image by address or by build ID. rdar://124913332
This commit is contained in:
121
stdlib/public/RuntimeModule/ImageMap+Linux.swift
Normal file
121
stdlib/public/RuntimeModule/ImageMap+Linux.swift
Normal file
@@ -0,0 +1,121 @@
|
||||
//===--- ImageMap+Linux.swift --------------------------------*- swift -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Linux specifics for ImageMap capture.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if os(Linux)
|
||||
|
||||
import Swift
|
||||
|
||||
#if canImport(Glibc)
|
||||
internal import Glibc
|
||||
#elseif canImport(Musl)
|
||||
internal import Musl
|
||||
#endif
|
||||
|
||||
internal import BacktracingImpl.ImageFormats.Elf
|
||||
|
||||
extension ImageMap {
|
||||
|
||||
private struct AddressRange {
|
||||
var low: Address = 0
|
||||
var high: Address = 0
|
||||
}
|
||||
|
||||
@_specialize(exported: true, kind: full, where M == UnsafeLocalMemoryReader)
|
||||
@_specialize(exported: true, kind: full, where M == RemoteMemoryReader)
|
||||
@_specialize(exported: true, kind: full, where M == LocalMemoryReader)
|
||||
@_spi(Internal)
|
||||
public static func capture<M: MemoryReader>(
|
||||
using reader: M,
|
||||
forProcess pid: Int? = nil
|
||||
) -> ImageMap {
|
||||
var images: [Image] = []
|
||||
|
||||
let wordSize: WordSize
|
||||
|
||||
#if arch(x86_64) || arch(arm64) || arch(arm64_32)
|
||||
wordSize = .sixtyFourBit
|
||||
#elseif arch(i386) || arch(arm)
|
||||
wordSize = .thirtyTwoBit
|
||||
#endif
|
||||
|
||||
let path: String
|
||||
if let pid = pid {
|
||||
path = "/proc/\(pid)/maps"
|
||||
} else {
|
||||
path = "/proc/self/maps"
|
||||
}
|
||||
|
||||
guard let procMaps = readString(from: path) else {
|
||||
return ImageMap(images: [], wordSize: wordSize)
|
||||
}
|
||||
|
||||
// Find all the mapped files and get high/low ranges
|
||||
var mappedFiles: [Substring:AddressRange] = [:]
|
||||
for match in ProcMapsScanner(procMaps) {
|
||||
let path = stripWhitespace(match.pathname)
|
||||
if match.inode == "0" || path == "" {
|
||||
continue
|
||||
}
|
||||
guard let start = Address(match.start, radix: 16),
|
||||
let end = Address(match.end, radix: 16) else {
|
||||
continue
|
||||
}
|
||||
|
||||
if let range = mappedFiles[path] {
|
||||
mappedFiles[path] = AddressRange(low: Swift.min(start, range.low),
|
||||
high: Swift.max(end, range.high))
|
||||
} else {
|
||||
mappedFiles[path] = AddressRange(low: start,
|
||||
high: end)
|
||||
}
|
||||
}
|
||||
|
||||
// Look at each mapped file to see if it's an ELF image
|
||||
for (path, range) in mappedFiles {
|
||||
// Extract the filename from path
|
||||
let name: Substring
|
||||
if let slashIndex = path.lastIndex(of: "/") {
|
||||
name = path.suffix(from: path.index(after: slashIndex))
|
||||
} else {
|
||||
name = path
|
||||
}
|
||||
|
||||
// Inspect the image and extract the UUID and end of text
|
||||
guard let (endOfText, uuid) = getElfImageInfo(
|
||||
at: M.Address(exactly: range.low)!,
|
||||
using: reader
|
||||
) else {
|
||||
// Not an ELF image
|
||||
continue
|
||||
}
|
||||
|
||||
let image = Image(name: String(name),
|
||||
path: String(path),
|
||||
uniqueID: uuid,
|
||||
baseAddress: range.low,
|
||||
endOfText: Address(endOfText))
|
||||
|
||||
images.append(image)
|
||||
}
|
||||
|
||||
images.sort(by: { $0.baseAddress < $1.baseAddress })
|
||||
|
||||
return ImageMap(images: images, wordSize: wordSize)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // os(Linux)
|
||||
Reference in New Issue
Block a user