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:
91
stdlib/public/RuntimeModule/ImageMap+Darwin.swift
Normal file
91
stdlib/public/RuntimeModule/ImageMap+Darwin.swift
Normal file
@@ -0,0 +1,91 @@
|
||||
//===--- 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)
|
||||
Reference in New Issue
Block a user