@@ -150,19 +150,24 @@ std::vector<Symbol *> SymbolTable::findByVersion(SymbolVersion ver) {
150
150
return {};
151
151
}
152
152
153
- std::vector<Symbol *> SymbolTable::findAllByVersion (SymbolVersion ver) {
153
+ std::vector<Symbol *> SymbolTable::findAllByVersion (SymbolVersion ver,
154
+ bool includeNonDefault) {
154
155
std::vector<Symbol *> res;
155
156
SingleStringMatcher m (ver.name );
156
157
157
158
if (ver.isExternCpp ) {
158
159
for (auto &p : getDemangledSyms ())
159
160
if (m.match (p.first ()))
160
- res.insert (res.end (), p.second .begin (), p.second .end ());
161
+ for (Symbol *sym : p.second )
162
+ if (includeNonDefault || !sym->getName ().contains (' @' ))
163
+ res.push_back (sym);
161
164
return res;
162
165
}
163
166
164
167
for (Symbol *sym : symVector)
165
- if (canBeVersioned (*sym) && m.match (sym->getName ()))
168
+ if (canBeVersioned (*sym) &&
169
+ (includeNonDefault || !sym->getName ().contains (' @' )) &&
170
+ m.match (sym->getName ()))
166
171
res.push_back (sym);
167
172
return res;
168
173
}
@@ -172,7 +177,7 @@ void SymbolTable::handleDynamicList() {
172
177
for (SymbolVersion &ver : config->dynamicList ) {
173
178
std::vector<Symbol *> syms;
174
179
if (ver.hasWildcard )
175
- syms = findAllByVersion (ver);
180
+ syms = findAllByVersion (ver, /* includeNonDefault= */ true );
176
181
else
177
182
syms = findByVersion (ver);
178
183
@@ -181,21 +186,12 @@ void SymbolTable::handleDynamicList() {
181
186
}
182
187
}
183
188
184
- // Set symbol versions to symbols. This function handles patterns
185
- // containing no wildcard characters .
186
- void SymbolTable::assignExactVersion (SymbolVersion ver, uint16_t versionId,
189
+ // Set symbol versions to symbols. This function handles patterns containing no
190
+ // wildcard characters. Return false if no symbol definition matches ver .
191
+ bool SymbolTable::assignExactVersion (SymbolVersion ver, uint16_t versionId,
187
192
StringRef versionName) {
188
- if (ver.hasWildcard )
189
- return ;
190
-
191
193
// Get a list of symbols which we need to assign the version to.
192
194
std::vector<Symbol *> syms = findByVersion (ver);
193
- if (syms.empty ()) {
194
- if (!config->undefinedVersion )
195
- error (" version script assignment of '" + versionName + " ' to symbol '" +
196
- ver.name + " ' failed: symbol not defined" );
197
- return ;
198
- }
199
195
200
196
auto getName = [](uint16_t ver) -> std::string {
201
197
if (ver == VER_NDX_LOCAL)
@@ -207,10 +203,10 @@ void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
207
203
208
204
// Assign the version.
209
205
for (Symbol *sym : syms) {
210
- // Skip symbols containing version info because symbol versions
211
- // specified by symbol names take precedence over version scripts.
212
- // See parseSymbolVersion().
213
- if (sym->getName ().contains (' @' ))
206
+ // For a non-local versionId, skip symbols containing version info because
207
+ // symbol versions specified by symbol names take precedence over version
208
+ // scripts. See parseSymbolVersion().
209
+ if (versionId != VER_NDX_LOCAL && sym->getName ().contains (' @' ))
214
210
continue ;
215
211
216
212
// If the version has not been assigned, verdefIndex is -1. Use an arbitrary
@@ -225,13 +221,15 @@ void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
225
221
warn (" attempt to reassign symbol '" + ver.name + " ' of " +
226
222
getName (sym->versionId ) + " to " + getName (versionId));
227
223
}
224
+ return !syms.empty ();
228
225
}
229
226
230
- void SymbolTable::assignWildcardVersion (SymbolVersion ver, uint16_t versionId) {
227
+ void SymbolTable::assignWildcardVersion (SymbolVersion ver, uint16_t versionId,
228
+ bool includeNonDefault) {
231
229
// Exact matching takes precedence over fuzzy matching,
232
230
// so we set a version to a symbol only if no version has been assigned
233
231
// to the symbol. This behavior is compatible with GNU.
234
- for (Symbol *sym : findAllByVersion (ver))
232
+ for (Symbol *sym : findAllByVersion (ver, includeNonDefault ))
235
233
if (sym->verdefIndex == UINT32_C (-1 )) {
236
234
sym->verdefIndex = 0 ;
237
235
sym->versionId = versionId;
@@ -244,26 +242,57 @@ void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId) {
244
242
// script file, the script does not actually define any symbol version,
245
243
// but just specifies symbols visibilities.
246
244
void SymbolTable::scanVersionScript () {
245
+ SmallString<128 > buf;
247
246
// First, we assign versions to exact matching symbols,
248
247
// i.e. version definitions not containing any glob meta-characters.
249
- for (VersionDefinition &v : config->versionDefinitions )
250
- for (SymbolVersion &pat : v.patterns )
251
- assignExactVersion (pat, v.id , v.name );
248
+ std::vector<Symbol *> syms;
249
+ for (VersionDefinition &v : config->versionDefinitions ) {
250
+ auto assignExact = [&](SymbolVersion pat, uint16_t id, StringRef ver) {
251
+ bool found = assignExactVersion (pat, id, ver);
252
+ found |= assignExactVersion ({(pat.name + " @" + v.name ).toStringRef (buf),
253
+ pat.isExternCpp , /* hasWildCard=*/ false },
254
+ id, ver);
255
+ if (!found && !config->undefinedVersion )
256
+ errorOrWarn (" version script assignment of '" + ver + " ' to symbol '" +
257
+ pat.name + " ' failed: symbol not defined" );
258
+ };
259
+ for (SymbolVersion &pat : v.nonLocalPatterns )
260
+ if (!pat.hasWildcard )
261
+ assignExact (pat, v.id , v.name );
262
+ for (SymbolVersion pat : v.localPatterns )
263
+ if (!pat.hasWildcard )
264
+ assignExact (pat, VER_NDX_LOCAL, " local" );
265
+ }
252
266
253
267
// Next, assign versions to wildcards that are not "*". Note that because the
254
268
// last match takes precedence over previous matches, we iterate over the
255
269
// definitions in the reverse order.
256
- for (VersionDefinition &v : llvm::reverse (config->versionDefinitions ))
257
- for (SymbolVersion &pat : v.patterns )
270
+ auto assignWildcard = [&](SymbolVersion pat, uint16_t id, StringRef ver) {
271
+ assignWildcardVersion (pat, id, /* includeNonDefault=*/ false );
272
+ assignWildcardVersion ({(pat.name + " @" + ver).toStringRef (buf),
273
+ pat.isExternCpp , /* hasWildCard=*/ true },
274
+ id,
275
+ /* includeNonDefault=*/ true );
276
+ };
277
+ for (VersionDefinition &v : llvm::reverse (config->versionDefinitions )) {
278
+ for (SymbolVersion &pat : v.nonLocalPatterns )
258
279
if (pat.hasWildcard && pat.name != " *" )
259
- assignWildcardVersion (pat, v.id );
280
+ assignWildcard (pat, v.id , v.name );
281
+ for (SymbolVersion &pat : v.localPatterns )
282
+ if (pat.hasWildcard && pat.name != " *" )
283
+ assignWildcard (pat, VER_NDX_LOCAL, v.name );
284
+ }
260
285
261
286
// Then, assign versions to "*". In GNU linkers they have lower priority than
262
287
// other wildcards.
263
- for (VersionDefinition &v : config->versionDefinitions )
264
- for (SymbolVersion &pat : v.patterns )
288
+ for (VersionDefinition &v : config->versionDefinitions ) {
289
+ for (SymbolVersion &pat : v.nonLocalPatterns )
265
290
if (pat.hasWildcard && pat.name == " *" )
266
- assignWildcardVersion (pat, v.id );
291
+ assignWildcard (pat, v.id , v.name );
292
+ for (SymbolVersion &pat : v.localPatterns )
293
+ if (pat.hasWildcard && pat.name == " *" )
294
+ assignWildcard (pat, VER_NDX_LOCAL, v.name );
295
+ }
267
296
268
297
// Symbol themselves might know their versions because symbols
269
298
// can contain versions in the form of <name>@<version>.
0 commit comments