Skip to content

Commit 5f6dd33

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 made --no-allow-shlib-undefined stronger: * There is a DSO undef that can be satisfied by a SharedSymbol. * The SharedSymbol is overridden by a hidden visibility Defined. * The hidden visibility Defined can be garbage-collected (it is not part of .dynsym and is not marked as live). When all the conditions are satisfied, the new --no-allow-shlib-undefined code reports an error. 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, add a new bit in Symbols::flags and relax the --no-allow-shlib-undefined check to before commit 1981b1b. --- Possible future extension: create a linker option to error about the cases ignored by this patch, and generalize it to included garbage-collected Defined and DSO definitions. I have managed to identify several unintended hidden/default duplicate symbol issues internally. I haven't yet identified an entirely legitimate use case of a hidden Defined "preempting" a DSO undef/def. In addition, the option can apply to DSO definitions as well, not just `requiredSymbols`.
1 parent 49168b2 commit 5f6dd33

File tree

4 files changed

+11
-1
lines changed

4 files changed

+11
-1
lines changed

lld/ELF/InputFiles.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,7 @@ template <class ELFT> void SharedFile::parse() {
15451545
auto *s = symtab.addSymbol(
15461546
SharedSymbol{*this, name, sym.getBinding(), sym.st_other,
15471547
sym.getType(), sym.st_value, sym.st_size, alignment});
1548+
s->setFlags(HAS_SHARED_DEF);
15481549
if (s->file == this)
15491550
s->verdefIndex = ver;
15501551
}
@@ -1562,6 +1563,7 @@ template <class ELFT> void SharedFile::parse() {
15621563
auto *s = symtab.addSymbol(
15631564
SharedSymbol{*this, saver().save(name), sym.getBinding(), sym.st_other,
15641565
sym.getType(), sym.st_value, sym.st_size, alignment});
1566+
s->setFlags(HAS_SHARED_DEF);
15651567
if (s->file == this)
15661568
s->verdefIndex = idx;
15671569
}

lld/ELF/Symbols.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ enum {
5454
NEEDS_TLSGD_TO_IE = 1 << 6,
5555
NEEDS_GOT_DTPREL = 1 << 7,
5656
NEEDS_TLSIE = 1 << 8,
57+
HAS_SHARED_DEF = 1 << 9,
5758
};
5859

5960
// Some index properties of a symbol are stored separately in this auxiliary

lld/ELF/Writer.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2016,6 +2016,11 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
20162016
// to catch more cases. That is too much for us. Our approach resembles
20172017
// the one used in ld.gold, achieves a good balance to be useful but not
20182018
// too smart.
2019+
//
2020+
// If a DSO reference is resolved by a SharedSymbol, but the SharedSymbol
2021+
// is overridden by a hidden visibility Defined (which is later discarded
2022+
// due to GC), don't report the diagnostic. However, this may indicate an
2023+
// unintended SharedSymbol.
20192024
for (SharedFile *file : ctx.sharedFiles) {
20202025
bool allNeededIsKnown =
20212026
llvm::all_of(file->dtNeeded, [&](StringRef needed) {
@@ -2024,6 +2029,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
20242029
if (!allNeededIsKnown)
20252030
continue;
20262031
for (Symbol *sym : file->requiredSymbols) {
2032+
if (sym->hasFlag(HAS_SHARED_DEF))
2033+
continue;
20272034
if (sym->isUndefined() && !sym->isWeak()) {
20282035
diagnose("undefined reference due to --no-allow-shlib-undefined: " +
20292036
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)