Skip to content

Commit 44efb59

Browse files
authored
Merge pull request #72980 from mikeash/prespecialized-metadata-disable-per-process-6.0
[6.0][Runtime] Allow disabling/enabling prespecializations library per-process.
2 parents 7ce4055 + 7e11e62 commit 44efb59

File tree

3 files changed

+118
-15
lines changed

3 files changed

+118
-15
lines changed

include/swift/Runtime/LibPrespecialized.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@ struct LibPrespecializedData {
3131
uint32_t minorVersion;
3232

3333
TargetPointer<Runtime, const void> metadataMap;
34+
TargetPointer<Runtime, const void> disabledProcessesTable;
3435

3536
static constexpr uint32_t currentMajorVersion = 1;
36-
static constexpr uint32_t currentMinorVersion = 1;
37+
static constexpr uint32_t currentMinorVersion = 2;
38+
39+
static constexpr uint32_t minorVersionWithDisabledProcessesTable = 2;
3740

3841
// Helpers for retrieving the metadata map in-process.
3942
static bool stringIsNull(const char *str) { return str == nullptr; }
@@ -43,6 +46,12 @@ struct LibPrespecializedData {
4346
const MetadataMap *getMetadataMap() const {
4447
return reinterpret_cast<const MetadataMap *>(metadataMap);
4548
}
49+
50+
const char *const *getDisabledProcessesTable() const {
51+
if (minorVersion < minorVersionWithDisabledProcessesTable)
52+
return nullptr;
53+
return reinterpret_cast<const char *const *>(disabledProcessesTable);
54+
}
4655
};
4756

4857
const LibPrespecializedData<InProcess> *getLibPrespecializedData();

stdlib/public/runtime/EnvironmentVariables.def

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,19 @@ VARIABLE(SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED, bool, true,
9292
"Enable use of prespecializations library.")
9393

9494
VARIABLE(SWIFT_DEBUG_LIB_PRESPECIALIZED_PATH, string, "",
95-
"A path to a prespecializations library to use at runtime. In order to"
96-
"be used, this library must be loaded into the process by other means"
97-
"(such as DYLD_INSERT_LIBRARIES) before Swift tries to use it.")
95+
"A path to a prespecializations library to use at runtime. In order "
96+
"to be used, this library must be loaded into the process by other "
97+
"means (such as DYLD_INSERT_LIBRARIES) before Swift tries to use it.")
98+
99+
VARIABLE(SWIFT_DEBUG_LIB_PRESPECIALIZED_DISABLED_PROCESSES, string, "",
100+
"A colon-separated list of process names where the prespecializations "
101+
"library will be forcibly disabled.")
102+
103+
VARIABLE(SWIFT_DEBUG_LIB_PRESPECIALIZED_ENABLED_PROCESSES, string, "",
104+
"A colon-separated list of process names where the prespecializations "
105+
"library will be forcibly enabled. This overrides the disabled "
106+
"processes list in the prespecializations library, as well as the "
107+
"list in SWIFT_DEBUG_LIB_PRESPECIALIZED_DISABLED_PROCESSES.")
98108

99109
VARIABLE(SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED_LOGGING, bool, false,
100110
"Enable debug logging of prespecializations library use.")

stdlib/public/runtime/LibPrespecialized.cpp

Lines changed: 95 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,85 @@ using namespace swift;
3232

3333
static std::atomic<bool> disablePrespecializedMetadata = false;
3434

35+
static bool prespecializedLoggingEnabled = false;
36+
37+
#define LOG(fmt, ...) \
38+
do { \
39+
if (SWIFT_UNLIKELY(prespecializedLoggingEnabled)) \
40+
fprintf(stderr, "Prespecializations library: " fmt "\n", __VA_ARGS__); \
41+
} while (0)
42+
43+
static bool environmentProcessListContainsProcess(const char *list,
44+
const char *progname) {
45+
auto prognameLen = strlen(progname);
46+
47+
const char *cursor = list;
48+
while (true) {
49+
const char *next = strchr(cursor, ':');
50+
if (!next) {
51+
// Last entry in the list. Compare with the entire rest of the string.
52+
return strcmp(progname, cursor) == 0;
53+
}
54+
55+
// Entry at beginning or middle of the list. Compare against this substring.
56+
size_t len = next - cursor;
57+
if (len == prognameLen && strncmp(cursor, progname, len) == 0)
58+
return true;
59+
60+
cursor = next + 1;
61+
}
62+
}
63+
64+
static bool isThisProcessEnabled(const LibPrespecializedData<InProcess> *data) {
65+
extern const char *__progname;
66+
67+
if (!__progname)
68+
return true;
69+
70+
auto envEnabledProcesses =
71+
runtime::environment::SWIFT_DEBUG_LIB_PRESPECIALIZED_ENABLED_PROCESSES();
72+
if (envEnabledProcesses && *envEnabledProcesses) {
73+
if (environmentProcessListContainsProcess(envEnabledProcesses,
74+
__progname)) {
75+
LOG("Found %s in SWIFT_DEBUG_LIB_PRESPECIALIZED_ENABLED_PROCESSES, "
76+
"enabling",
77+
__progname);
78+
return true;
79+
}
80+
}
81+
82+
auto envDisabledProcesses =
83+
runtime::environment::SWIFT_DEBUG_LIB_PRESPECIALIZED_DISABLED_PROCESSES();
84+
if (envDisabledProcesses && *envDisabledProcesses) {
85+
if (environmentProcessListContainsProcess(envDisabledProcesses,
86+
__progname)) {
87+
LOG("Found %s in SWIFT_DEBUG_LIB_PRESPECIALIZED_DISABLED_PROCESSES, "
88+
"disabling",
89+
__progname);
90+
return false;
91+
}
92+
}
93+
94+
if (auto *disabledProcesses = data->getDisabledProcessesTable()) {
95+
auto *cursor = disabledProcesses;
96+
while (auto *name = *cursor) {
97+
if (strcmp(name, __progname) == 0) {
98+
LOG("Found %s in disabled processes list, disabling", name);
99+
return false;
100+
}
101+
cursor++;
102+
}
103+
}
104+
105+
return true;
106+
}
107+
35108
static const LibPrespecializedData<InProcess> *findLibPrespecialized() {
36-
if (!runtime::environment::SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED())
109+
if (!runtime::environment::SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED()) {
110+
LOG("Disabling, SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED = %d",
111+
runtime::environment::SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED());
37112
return nullptr;
113+
}
38114

39115
const void *dataPtr = nullptr;
40116
#if USE_DLOPEN
@@ -51,15 +127,22 @@ static const LibPrespecializedData<InProcess> *findLibPrespecialized() {
51127
}
52128

53129
dataPtr = dlsym(handle, LIB_PRESPECIALIZED_TOP_LEVEL_SYMBOL_NAME);
130+
LOG("Loaded custom library from %s, found dataPtr %p", path, dataPtr);
54131
}
55132
#if DYLD_GET_SWIFT_PRESPECIALIZED_DATA_DEFINED
56133
else if (SWIFT_RUNTIME_WEAK_CHECK(_dyld_get_swift_prespecialized_data)) {
57134
// Disable the prespecializations library if anything in the shared cache is
58135
// overridden. Eventually we want to be cleverer and only disable the
59136
// prespecializations that have been invalidated, but we'll start with the
60137
// simplest approach.
61-
if (!dyld_shared_cache_some_image_overridden())
138+
if (!dyld_shared_cache_some_image_overridden()) {
62139
dataPtr = SWIFT_RUNTIME_WEAK_USE(_dyld_get_swift_prespecialized_data());
140+
LOG("Got dataPtr %p from _dyld_get_swift_prespecialized_data", dataPtr);
141+
} else {
142+
LOG("Not calling _dyld_get_swift_prespecialized_data "
143+
"dyld_shared_cache_some_image_overridden = %d",
144+
dyld_shared_cache_some_image_overridden());
145+
}
63146
}
64147
#endif
65148
#endif
@@ -70,8 +153,16 @@ static const LibPrespecializedData<InProcess> *findLibPrespecialized() {
70153
auto *data =
71154
reinterpret_cast<const LibPrespecializedData<InProcess> *>(dataPtr);
72155
if (data->majorVersion !=
73-
LibPrespecializedData<InProcess>::currentMajorVersion)
156+
LibPrespecializedData<InProcess>::currentMajorVersion) {
157+
LOG("Unknown major version %" PRIu32 ", disabling", data->majorVersion);
74158
return nullptr;
159+
}
160+
161+
if (!isThisProcessEnabled(data))
162+
return nullptr;
163+
164+
LOG("Returning data %p, major version %" PRIu32 " minor %" PRIu32, data,
165+
data->majorVersion, data->minorVersion);
75166

76167
return data;
77168
}
@@ -85,13 +176,12 @@ struct LibPrespecializedState {
85176
}
86177
};
87178

88-
bool loggingEnabled;
89179
const LibPrespecializedData<InProcess> *data;
90180
AddressRange sharedCacheRange{0, 0};
91181
AddressRange metadataAllocatorInitialPoolRange{0, 0};
92182

93183
LibPrespecializedState() {
94-
loggingEnabled =
184+
prespecializedLoggingEnabled =
95185
runtime::environment::SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED_LOGGING();
96186
data = findLibPrespecialized();
97187

@@ -112,12 +202,6 @@ struct LibPrespecializedState {
112202

113203
static Lazy<LibPrespecializedState> LibPrespecialized;
114204

115-
#define LOG(fmt, ...) \
116-
do { \
117-
if (SWIFT_UNLIKELY(prespecialized.loggingEnabled)) \
118-
fprintf(stderr, "Prespecializations library: " fmt "\n", __VA_ARGS__); \
119-
} while (0)
120-
121205
const LibPrespecializedData<InProcess> *swift::getLibPrespecializedData() {
122206
return SWIFT_LAZY_CONSTANT(findLibPrespecialized());
123207
}

0 commit comments

Comments
 (0)