mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Runtime] Add a function pointer for intercepting swift_willThrow calls.
rdar://problem/53400364
This commit is contained in:
@@ -27,6 +27,7 @@ add_swift_target_library(swiftStdlibUnittest ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES}
|
||||
Statistics.swift
|
||||
StdlibCoreExtras.swift
|
||||
StringConvertible.swift
|
||||
SymbolLookup.swift
|
||||
TestHelpers.swift
|
||||
TypeIndexed.swift
|
||||
|
||||
|
||||
49
stdlib/private/StdlibUnittest/SymbolLookup.swift
Normal file
49
stdlib/private/StdlibUnittest/SymbolLookup.swift
Normal file
@@ -0,0 +1,49 @@
|
||||
//===--- SymbolLookup.swift -----------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2019 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
import Darwin
|
||||
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin) || os(Haiku)
|
||||
import Glibc
|
||||
#elseif os(Windows)
|
||||
import MSVCRT
|
||||
import WinSDK
|
||||
#else
|
||||
#error("Unsupported platform")
|
||||
#endif
|
||||
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)
|
||||
#elseif os(Linux)
|
||||
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: 0)
|
||||
#elseif os(Android)
|
||||
#if arch(arm)
|
||||
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: 0xffffffff as UInt)
|
||||
#elseif arch(arm64)
|
||||
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: 0)
|
||||
#else
|
||||
#error("Unsupported platform")
|
||||
#endif
|
||||
#elseif os(Windows)
|
||||
let hStdlibCore: HMODULE = GetModuleHandleA("swiftCore.dll")!
|
||||
#else
|
||||
#error("Unsupported platform")
|
||||
#endif
|
||||
|
||||
public func pointerToSwiftCoreSymbol(name: String) -> UnsafeMutableRawPointer? {
|
||||
#if os(Windows)
|
||||
return unsafeBitCast(GetProcAddress(hStdlibCore, name),
|
||||
to: UnsafeMutableRawPointer?.self)
|
||||
#else
|
||||
return dlsym(RTLD_DEFAULT, name)
|
||||
#endif
|
||||
}
|
||||
@@ -37,6 +37,7 @@ set(swift_runtime_sources
|
||||
CygwinPort.cpp
|
||||
Demangle.cpp
|
||||
Enum.cpp
|
||||
ErrorObjectCommon.cpp
|
||||
ErrorObjectConstants.cpp
|
||||
ErrorObjectNative.cpp
|
||||
Errors.cpp
|
||||
|
||||
@@ -598,12 +598,5 @@ swift::swift_errorRelease(SwiftError *error) {
|
||||
return objc_release((id)error);
|
||||
}
|
||||
|
||||
/// Breakpoint hook for debuggers.
|
||||
SWIFT_CC(swift) void
|
||||
swift::swift_willThrow(SWIFT_CONTEXT void *unused,
|
||||
SWIFT_ERROR_RESULT SwiftError **error) {
|
||||
// empty
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
38
stdlib/public/runtime/ErrorObjectCommon.cpp
Normal file
38
stdlib/public/runtime/ErrorObjectCommon.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
//===--- ErrorObjectCommon.cpp - Recoverable error object -----------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2019 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This implements the parts of the standard Error protocol type which are
|
||||
// shared between the ObjC-interoperable implementation and the native
|
||||
// implementation. The parts specific to each implementation can be found in
|
||||
// ErrorObject.mm (for the ObjC-interoperable parts) and ErrorObjectNative.cpp.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Runtime/Concurrent.h"
|
||||
#include "swift/Runtime/Config.h"
|
||||
#include "ErrorObject.h"
|
||||
#include "ErrorObjectTestSupport.h"
|
||||
|
||||
using namespace swift;
|
||||
|
||||
void (*swift::_swift_willThrow)(SwiftError *error);
|
||||
|
||||
/// Breakpoint hook for debuggers, and calls _swift_willThrow if set.
|
||||
SWIFT_CC(swift) void
|
||||
swift::swift_willThrow(SWIFT_CONTEXT void *unused,
|
||||
SWIFT_ERROR_RESULT SwiftError **error) {
|
||||
// Cheap check to bail out early, since we expect there to be no callbacks
|
||||
// the vast majority of the time.
|
||||
if (SWIFT_LIKELY(!_swift_willThrow))
|
||||
return;
|
||||
_swift_willThrow(*error);
|
||||
}
|
||||
@@ -106,11 +106,4 @@ swift::swift_getErrorValue(const SwiftError *errorObject,
|
||||
out->errorConformance = errorObject->errorConformance;
|
||||
}
|
||||
|
||||
/// Breakpoint hook for debuggers.
|
||||
SWIFT_CC(swift) void
|
||||
swift::swift_willThrow(SWIFT_CONTEXT void *unused,
|
||||
SWIFT_ERROR_RESULT SwiftError **error) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
26
stdlib/public/runtime/ErrorObjectTestSupport.h
Normal file
26
stdlib/public/runtime/ErrorObjectTestSupport.h
Normal file
@@ -0,0 +1,26 @@
|
||||
//===--- ErrorObjectTestSupport.h - Support for Instruments.app -*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2019 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Swift runtime support for tests involving errors.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_RUNTIME_ERROROBJECT_TEST_SUPPORT_H
|
||||
#define SWIFT_RUNTIME_ERROROBJECT_TEST_SUPPORT_H
|
||||
|
||||
namespace swift {
|
||||
|
||||
SWIFT_RUNTIME_EXPORT void (*_swift_willThrow)(SwiftError *error);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -191,5 +191,23 @@ ErrorTests.test("test dealloc empty error box") {
|
||||
}
|
||||
}
|
||||
|
||||
var errors: [Error] = []
|
||||
ErrorTests.test("willThrow") {
|
||||
typealias WillThrow = @convention(c) (Error) -> Void
|
||||
let willThrow = pointerToSwiftCoreSymbol(name: "_swift_willThrow")!
|
||||
willThrow.storeBytes(of: { errors.append($0) }, as: WillThrow.self)
|
||||
expectTrue(errors.isEmpty)
|
||||
do {
|
||||
throw UnsignedError.negativeOne
|
||||
} catch {}
|
||||
expectEqual(UnsignedError.self, type(of: errors.last!))
|
||||
|
||||
do {
|
||||
throw SillyError.JazzHands
|
||||
} catch {}
|
||||
expectEqual(2, errors.count)
|
||||
expectEqual(SillyError.self, type(of: errors.last!))
|
||||
}
|
||||
|
||||
runAllTests()
|
||||
|
||||
|
||||
@@ -592,39 +592,9 @@ Runtime.test("Struct layout with reference storage types") {
|
||||
}
|
||||
|
||||
Runtime.test("SwiftError layout constants for LLDB") {
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)
|
||||
#elseif os(Linux)
|
||||
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: 0)
|
||||
#elseif os(Android)
|
||||
#if arch(arm)
|
||||
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: 0xffffffff as UInt)
|
||||
#elseif arch(arm64)
|
||||
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: 0)
|
||||
#else
|
||||
_UnimplementedError()
|
||||
#endif
|
||||
#elseif os(Windows)
|
||||
let hStdlibCore: HMODULE = GetModuleHandleA("swiftCore.dll")!
|
||||
#else
|
||||
_UnimplementedError()
|
||||
#endif
|
||||
let offsetof_SwiftError_typeMetadata = pointerToSwiftCoreSymbol(name: "_swift_lldb_offsetof_SwiftError_typeMetadata")!
|
||||
let sizeof_SwiftError = pointerToSwiftCoreSymbol(name: "_swift_lldb_sizeof_SwiftError")!
|
||||
|
||||
#if os(Windows)
|
||||
let offsetof_SwiftError_typeMetadata: UnsafeRawPointer =
|
||||
unsafeBitCast(GetProcAddress(hStdlibCore,
|
||||
"_swift_lldb_offsetof_SwiftError_typeMetadata")!,
|
||||
to: UnsafeRawPointer.self)
|
||||
let sizeof_SwiftError: UnsafeRawPointer =
|
||||
unsafeBitCast(GetProcAddress(hStdlibCore,
|
||||
"_swift_lldb_sizeof_SwiftError")!,
|
||||
to: UnsafeRawPointer.self)
|
||||
#else
|
||||
let offsetof_SwiftError_typeMetadata =
|
||||
dlsym(RTLD_DEFAULT, "_swift_lldb_offsetof_SwiftError_typeMetadata")!
|
||||
let sizeof_SwiftError =
|
||||
dlsym(RTLD_DEFAULT, "_swift_lldb_sizeof_SwiftError")!
|
||||
#endif
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
#if arch(i386) || arch(arm)
|
||||
expectEqual(20, offsetof_SwiftError_typeMetadata.load(as: UInt.self))
|
||||
|
||||
Reference in New Issue
Block a user