Files
swift-mirror/stdlib/public/RuntimeModule/ImageMap+Darwin.swift
Alastair Houghton 0e3e9efcd3 [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
2025-01-17 10:09:36 +00:00

92 lines
2.8 KiB
Swift

//===--- ImageMap+Darwin.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
//
//===----------------------------------------------------------------------===//
//
// Darwin specifics for ImageMap capture.
//
//===----------------------------------------------------------------------===//
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
import Swift
internal import Darwin
internal import BacktracingImpl.OS.Darwin
extension ImageMap {
private static func withDyldProcessInfo<T>(for task: task_t,
fn: (OpaquePointer?) throws -> T)
rethrows -> T {
var kret = kern_return_t(KERN_SUCCESS)
let dyldInfo = _dyld_process_info_create(task, 0, &kret)
if kret != KERN_SUCCESS {
fatalError("error: cannot create dyld process info")
}
defer {
_dyld_process_info_release(dyldInfo)
}
return try fn(dyldInfo)
}
@_spi(Internal)
public static func capture(for process: Any) -> ImageMap {
var images: [Image] = []
let task = process as! task_t
withDyldProcessInfo(for: task) { dyldInfo in
_dyld_process_info_for_each_image(dyldInfo) {
(machHeaderAddress, uuid, path) in
if let path = path, let uuid = uuid {
let pathString = String(cString: path)
let theUUID = Array(UnsafeBufferPointer(start: uuid,
count: MemoryLayout<uuid_t>.size))
let name: String
if let slashIndex = pathString.lastIndex(of: "/") {
name = String(pathString.suffix(from:
pathString.index(after:slashIndex)))
} else {
name = pathString
}
// Find the end of the __TEXT segment
var endOfText = machHeaderAddress + 4096
_dyld_process_info_for_each_segment(dyldInfo, machHeaderAddress) {
address, size, name in
if let name = String(validatingCString: name!), name == "__TEXT" {
endOfText = address + size
}
}
images.append(Image(name: name,
path: pathString,
uniqueID: theUUID,
baseAddress: machHeaderAddress,
endOfText: endOfText))
}
}
}
images.sort(by: { $0.baseAddress < $1.baseAddress })
return ImageMap(images: images, wordSize: .sixtyFourBit)
}
}
#endif // os(macOS) || os(iOS) || os(watchOS) || os(tvOS)