File: GetSymbol.swift

package info (click to toggle)
swiftlang 6.2.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,856,264 kB
  • sloc: cpp: 9,995,718; ansic: 2,234,019; asm: 1,092,167; python: 313,940; objc: 82,726; f90: 80,126; lisp: 38,373; pascal: 25,580; sh: 20,378; ml: 5,058; perl: 4,751; makefile: 4,725; awk: 3,535; javascript: 3,018; xml: 918; fortran: 664; cs: 573; ruby: 396
file content (86 lines) | stat: -rw-r--r-- 3,404 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//
// 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 Swift project authors
//

#if os(Windows)
@_spi(Experimental) @_spi(ForToolsIntegrationOnly) private import _TestDiscovery
#endif
internal import _TestingInternals

#if !SWT_NO_DYNAMIC_LINKING

/// The platform-specific type of a loaded image handle.
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android)
typealias ImageAddress = UnsafeMutableRawPointer
#elseif os(Windows)
typealias ImageAddress = HMODULE
#else
#warning("Platform-specific implementation missing: Dynamic loading unavailable")
typealias ImageAddress = Never
#endif

/// The value of `RTLD_DEFAULT` on this platform.
///
/// This value is provided because `errno` is a complex macro on some platforms
/// and cannot be imported directly into Swift. As well, `RTLD_DEFAULT` is only
/// defined on Linux when `_GNU_SOURCE` is defined, so it is not sufficient to
/// declare a wrapper function in the internal module's Stubs.h file.
#if SWT_TARGET_OS_APPLE || os(FreeBSD) || os(OpenBSD)
private nonisolated(unsafe) let RTLD_DEFAULT = ImageAddress(bitPattern: -2)
#elseif os(Android) && _pointerBitWidth(_32)
private nonisolated(unsafe) let RTLD_DEFAULT = ImageAddress(bitPattern: UInt(0xFFFFFFFF))
#elseif os(Linux) || os(Android)
private nonisolated(unsafe) let RTLD_DEFAULT = ImageAddress(bitPattern: 0)
#endif

/// Use the platform's dynamic loader to get a symbol in the current process
/// at runtime.
///
/// - Parameters:
///   - handle: A platform-specific handle to the image in which to look for
///     `symbolName`. If `nil`, the symbol may be found in any image loaded
///     into the current process.
///   - symbolName: The name of the symbol to find.
///
/// - Returns: A pointer to the specified symbol, or `nil` if it could not be
///   found.
///
/// Callers looking for a symbol declared in a specific image should pass a
/// handle acquired from `dlopen()` as the `handle` argument. On Windows, pass
/// the result of `GetModuleHandleW()` or an equivalent function.
///
/// On Apple platforms and Linux, when `handle` is `nil`, this function is
/// equivalent to `dlsym(RTLD_DEFAULT, symbolName)`.
///
/// On Windows, there is no equivalent of `RTLD_DEFAULT`. It is simulated by
/// calling `EnumProcessModules()` and iterating over the returned handles
/// looking for one containing the given function.
func symbol(in handle: ImageAddress? = nil, named symbolName: String) -> UnsafeRawPointer? {
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android)
  dlsym(handle ?? RTLD_DEFAULT, symbolName).map(UnsafeRawPointer.init)
#elseif os(Windows)
  symbolName.withCString { symbolName in
    // If the caller supplied a module, use it.
    if let handle {
      return GetProcAddress(handle, symbolName).map {
        castCFunction($0, to: UnsafeRawPointer.self)
      }
    }

    return HMODULE.all.lazy
      .compactMap { GetProcAddress($0, symbolName) }
      .map { castCFunction($0, to: UnsafeRawPointer.self) }
      .first
  }
#else
#warning("Platform-specific implementation missing: Dynamic loading unavailable")
  return nil
#endif
}
#endif