-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathCompatibilityOverride.h
210 lines (188 loc) · 10.2 KB
/
CompatibilityOverride.h
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
//===--- CompatibilityOverride.h - Back-deployment patches ------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 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
//
//===----------------------------------------------------------------------===//
//
// The compatibility override system supports the back-deployment of
// bug fixes and ABI additions to existing Swift systems. This is
// primarily of interest on Apple platforms, since other platforms don't
// ship with a stable Swift runtime that cannot simply be replaced.
//
// The compatibility override system works as follows:
//
// 1. Certain runtime functions are "hooked" so that they can be replaced
// by the program at launch time. The function at the public symbol
// (we will use `swift_task_cancel` as a consistent example) is a
// thunk that either calls the standard implementation or its dynamic
// replacement. If a dynamic replacement is called, it is passed
// the standard implementation as an extra argument.
//
// 2. The public thunks are defined in different .cpp files throughout
// the runtime by the COMPATIBILITY_OVERRIDE macro below, triggered
// by an #include at the bottom of the file. The list of definitions
// to expand in a particular file is defined by the appropriate
// CompatibilityOverride*.def file for the current runtime component
// (i.e. either the main runtime or the concurrency runtime).
// The standard implementation must be defined in that file as a
// function with the suffix `Impl`, e.g. `swift_task_cancelImpl`.
// Usually the standard implementation should be static, and
// everywhere else in the runtime should call the public symbol.
//
// 3. The public thunks determine their replacement by calling an
// override accessor for the symbol the first time they are called.
// These accessors are named e.g. `swift::getOverride_swift_task_cancel`
// and are defined by CompatibilityOverride.cpp, which is built
// separately for each runtime component using different build
// settings.
//
// 4. The override accessors check for a Mach-O section with a specific
// name, and if it exists, they interpret the section as a struct
// with one field per replaceable function. The order of fields is
// determined by the appropriate CompatibilityOverride*.def file.
// The section name, the struct layout, and the function signatures of
// the replacement functions are the only parts of this which are ABI;
// everything else is an internal detail of the runtime which can be
// changed if useful.
//
// 5. The name of the Mach-O section is specific to both the current
// runtime component and the current version of the Swift runtime.
// Therefore, a compatibility override library always targets a
// specific runtime version and implicitly does nothing on other
// versions.
//
// 6. Compatibility override libraries define a Mach-O section with the
// appropriate name and layout for their target component and version
// and initialize the appropriate fields within it to the replacement
// functions. This occurs in the Overrides.cpp file in the library.
// Compatibility override libraries are linked against later override
// libraries for the same component, so if a patch needs to be applied
// to multiple versions, the last version can define public symbols
// that the other versions can use (assuming that any internal runtime
// structures are roughly compatible).
//
// 7. Compatibility override libraries are rebuilt with every Swift
// release in case that release requires new patches to the target
// runtime. They are therefore live code, unlike e.g. the
// back-deployment concurrency runtime.
//
// 8. The back-deployment concurrency runtime looks for the same section
// name as the OS-installed 5.6 runtime and therefore will be patched
// by the 5.6 compatibility override library.
//
//===----------------------------------------------------------------------===//
#ifndef COMPATIBILITY_OVERRIDE_H
#define COMPATIBILITY_OVERRIDE_H
#include "../runtime/Private.h"
#include "swift/Runtime/Concurrency.h"
#include "swift/Runtime/Metadata.h"
#include "swift/Runtime/Once.h"
#include "swift/Runtime/CMakeConfig.h"
#include <type_traits>
namespace swift {
// Macro utilities.
#define COMPATIBILITY_UNPAREN(...) __VA_ARGS__
#define COMPATIBILITY_CONCAT2(x, y) x##y
#define COMPATIBILITY_CONCAT(x, y) COMPATIBILITY_CONCAT2(x, y)
// This ridiculous construct will remove the parentheses from the argument and
// add a trailing comma, or will produce nothing when passed no argument. For
// example:
// COMPATIBILITY_UNPAREN_WITH_COMMA((1, 2, 3)) -> 1, 2, 3,
// COMPATIBILITY_UNPAREN_WITH_COMMA((4)) -> 4,
// COMPATIBILITY_UNPAREN_WITH_COMMA() ->
#define COMPATIBILITY_UNPAREN_WITH_COMMA(x) \
COMPATIBILITY_CONCAT(COMPATIBILITY_UNPAREN_ADD_TRAILING_COMMA_, \
COMPATIBILITY_UNPAREN_WITH_COMMA2 x)
#define COMPATIBILITY_UNPAREN_WITH_COMMA2(...) PARAMS(__VA_ARGS__)
#define COMPATIBILITY_UNPAREN_ADD_TRAILING_COMMA_PARAMS(...) __VA_ARGS__,
#define COMPATIBILITY_UNPAREN_ADD_TRAILING_COMMA_COMPATIBILITY_UNPAREN_WITH_COMMA2
// This ridiculous construct will preserve the parentheses around the argument,
// or will produce an empty pair of parentheses when passed no argument. For
// example:
// COMPATIBILITY_PAREN((1, 2, 3)) -> (1, 2, 3)
// COMPATIBILITY_PAREN((4)) -> (4)
// COMPATIBILITY_PAREN() -> ()
#define COMPATIBILITY_PAREN(x) \
COMPATIBILITY_CONCAT(COMPATIBILITY_PAREN_, COMPATIBILITY_PAREN2 x)
#define COMPATIBILITY_PAREN2(...) PARAMS(__VA_ARGS__)
#define COMPATIBILITY_PAREN_PARAMS(...) (__VA_ARGS__)
#define COMPATIBILITY_PAREN_COMPATIBILITY_PAREN2 ()
// Include path computation. Code that includes this file can write
// `#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH` to include the appropriate
// .def file for the current library.
#define COMPATIBILITY_OVERRIDE_INCLUDE_PATH_swiftRuntime \
"../CompatibilityOverride/CompatibilityOverrideRuntime.def"
#define COMPATIBILITY_OVERRIDE_INCLUDE_PATH_swift_Concurrency \
"../CompatibilityOverride/CompatibilityOverrideConcurrency.def"
#define COMPATIBILITY_OVERRIDE_INCLUDE_PATH \
COMPATIBILITY_CONCAT(COMPATIBILITY_OVERRIDE_INCLUDE_PATH_, \
SWIFT_TARGET_LIBRARY_NAME)
// Compatibility overrides are only supported on Darwin.
#ifdef SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT
#if !(defined(__APPLE__) && defined(__MACH__))
#undef SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT
#endif
#endif
#ifndef SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT
// Call directly through to the original implementation when we don't support
// overrides.
#define COMPATIBILITY_OVERRIDE(name, ret, attrs, ccAttrs, namespace, \
typedArgs, namedArgs) \
attrs ccAttrs ret namespace swift_##name COMPATIBILITY_PAREN(typedArgs) { \
return swift_##name##Impl COMPATIBILITY_PAREN(namedArgs); \
}
#else // #ifndef SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT
// Override section name computation. `COMPATIBILITY_OVERRIDE_SECTION_NAME` will
// resolve to string literal containing the appropriate section name for the
// current library.
// Turns into '__swift<major><minor>_hooks'
#define COMPATIBILITY_OVERRIDE_SECTION_NAME_swiftRuntime "__swift" \
SWIFT_VERSION_MAJOR \
SWIFT_VERSION_MINOR \
"_hooks"
// Turns into '__s<major><minor>async_hook'
#define COMPATIBILITY_OVERRIDE_SECTION_NAME_swift_Concurrency "__s" \
SWIFT_VERSION_MAJOR \
SWIFT_VERSION_MINOR \
"async_hook"
#define COMPATIBILITY_OVERRIDE_SECTION_NAME \
COMPATIBILITY_CONCAT(COMPATIBILITY_OVERRIDE_SECTION_NAME_, \
SWIFT_TARGET_LIBRARY_NAME)
// Create typedefs for function pointers to call the original implementation.
#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \
ccAttrs typedef ret(*Original_##name) COMPATIBILITY_PAREN(typedArgs);
#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH
// Create typedefs for override function pointers.
#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \
ccAttrs typedef ret (*Override_##name)(COMPATIBILITY_UNPAREN_WITH_COMMA( \
typedArgs) Original_##name originalImpl);
#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH
// Create declarations for getOverride functions.
#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \
Override_ ## name getOverride_ ## name();
#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH
/// Used to define an override point. The override point #defines the appropriate
/// OVERRIDE macro from CompatibilityOverride.def to this macro, then includes
/// the file to generate the override points. The original implementation of the
/// functionality must be available as swift_funcNameHereImpl.
#define COMPATIBILITY_OVERRIDE(name, ret, attrs, ccAttrs, namespace, \
typedArgs, namedArgs) \
attrs ccAttrs ret namespace swift_##name COMPATIBILITY_PAREN(typedArgs) { \
static Override_##name Override; \
static swift_once_t Predicate; \
swift_once( \
&Predicate, [](void *) { Override = getOverride_##name(); }, nullptr); \
if (Override != nullptr) \
return Override(COMPATIBILITY_UNPAREN_WITH_COMMA(namedArgs) \
swift_##name##Impl); \
return swift_##name##Impl COMPATIBILITY_PAREN(namedArgs); \
}
#endif // #else SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT
} /* end namespace swift */
#endif /* COMPATIBILITY_OVERRIDE_H */