Skip to content

Commit e390bda

Browse files
committed
[ELF] Suppress --no-allow-shlib-undefined diagnostic when a SharedSymbol is overridden by a hidden visibility Defined which is later discarded
Commit 1981b1b unexpectedly strengthened --no-allow-shlib-undefined to catch a kind of ODR violation. More precisely, when all three conditions are met, the new `--no-allow-shlib-undefined` code reports an error. * There is a DSO undef that has been satisfied by a definition from another DSO. * The `SharedSymbol` is overridden by a non-exported (usually of hidden visibility) definition in a relocatable object file (`Defined`). * The section containing the `Defined` is garbage-collected (it is not part of `.dynsym` and is not marked as live). Technically, the hidden Defined in the executable can be intentional: it can be meant to remain non-exported and not interact with any dynamic symbols of the same name that might exist in other DSOs. To allow for such use cases, allocate a new bit in Symbol and relax the --no-allow-shlib-undefined check to before commit 1981b1b.
1 parent 806f43e commit e390bda

File tree

4 files changed

+17
-4
lines changed

4 files changed

+17
-4
lines changed

lld/ELF/InputFiles.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,6 +1546,7 @@ template <class ELFT> void SharedFile::parse() {
15461546
auto *s = symtab.addSymbol(
15471547
SharedSymbol{*this, name, sym.getBinding(), sym.st_other,
15481548
sym.getType(), sym.st_value, sym.st_size, alignment});
1549+
s->dsoDefined = true;
15491550
if (s->file == this)
15501551
s->versionId = ver;
15511552
}
@@ -1563,6 +1564,7 @@ template <class ELFT> void SharedFile::parse() {
15631564
auto *s = symtab.addSymbol(
15641565
SharedSymbol{*this, saver().save(name), sym.getBinding(), sym.st_other,
15651566
sym.getType(), sym.st_value, sym.st_size, alignment});
1567+
s->dsoDefined = true;
15661568
if (s->file == this)
15671569
s->versionId = idx;
15681570
}

lld/ELF/Symbols.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -298,12 +298,13 @@ class Symbol {
298298
// of the symbol.
299299
uint8_t scriptDefined : 1;
300300

301+
// True if defined in a DSO. There may also be a definition in a relocatable
302+
// object file.
303+
uint8_t dsoDefined : 1;
304+
301305
// True if defined in a DSO as protected visibility.
302306
uint8_t dsoProtected : 1;
303307

304-
// True if targeted by a range extension thunk.
305-
uint8_t thunkAccessed : 1;
306-
307308
// Temporary flags used to communicate which symbol entries need PLT and GOT
308309
// entries during postScanRelocations();
309310
std::atomic<uint16_t> flags;
@@ -320,6 +321,9 @@ class Symbol {
320321
uint16_t versionId;
321322
uint8_t versionScriptAssigned : 1;
322323

324+
// True if targeted by a range extension thunk.
325+
uint8_t thunkAccessed : 1;
326+
323327
void setFlags(uint16_t bits) {
324328
flags.fetch_or(bits, std::memory_order_relaxed);
325329
}

lld/ELF/Writer.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2025,6 +2025,11 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
20252025
// to catch more cases. That is too much for us. Our approach resembles
20262026
// the one used in ld.gold, achieves a good balance to be useful but not
20272027
// too smart.
2028+
//
2029+
// If a DSO reference is resolved by a SharedSymbol, but the SharedSymbol
2030+
// is overridden by a hidden visibility Defined (which is later discarded
2031+
// due to GC), don't report the diagnostic. However, this may indicate an
2032+
// unintended SharedSymbol.
20282033
for (SharedFile *file : ctx.sharedFiles) {
20292034
bool allNeededIsKnown =
20302035
llvm::all_of(file->dtNeeded, [&](StringRef needed) {
@@ -2033,6 +2038,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
20332038
if (!allNeededIsKnown)
20342039
continue;
20352040
for (Symbol *sym : file->requiredSymbols) {
2041+
if (sym->dsoDefined)
2042+
continue;
20362043
if (sym->isUndefined() && !sym->isWeak()) {
20372044
diagnose("undefined reference due to --no-allow-shlib-undefined: " +
20382045
toString(*sym) + "\n>>> referenced by " + toString(file));

lld/test/ELF/allow-shlib-undefined.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
# RUN: not ld.lld --gc-sections main.o a.so def-hidden.o -o /dev/null 2>&1 | FileCheck %s
4141
## The definition def.so is ignored.
4242
# RUN: ld.lld -shared def.o -o def.so
43-
# RUN: not ld.lld --gc-sections main.o a.so def.so def-hidden.o -o /dev/null 2>&1 | FileCheck %s
43+
# RUN: ld.lld --gc-sections main.o a.so def.so def-hidden.o --fatal-warnings -o /dev/null
4444

4545
# CHECK-NOT: error:
4646
# CHECK: error: undefined reference due to --no-allow-shlib-undefined: x1{{$}}

0 commit comments

Comments
 (0)