Index: lld/trunk/ELF/Relocations.cpp =================================================================== --- lld/trunk/ELF/Relocations.cpp +++ lld/trunk/ELF/Relocations.cpp @@ -47,6 +47,7 @@ #include "SymbolTable.h" #include "Target.h" #include "Thunks.h" +#include "Strings.h" #include "llvm/Support/Endian.h" #include "llvm/Support/raw_ostream.h" @@ -519,6 +520,25 @@ return Addend; } +static void reportUndefined(SymbolBody &Sym) { + if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore) + return; + + if (Config->Shared && Sym.symbol()->Visibility == STV_DEFAULT && + Config->UnresolvedSymbols != UnresolvedPolicy::NoUndef) + return; + + std::string Msg = "undefined symbol: "; + Msg += Config->Demangle ? demangle(Sym.getName()) : Sym.getName().str(); + + if (Sym.File) + Msg += " in " + getFilename(Sym.File); + if (Config->UnresolvedSymbols == UnresolvedPolicy::Warn) + warn(Msg); + else + error(Msg); +} + // The reason we have to do this early scan is as follows // * To mmap the output file, we need to know the size // * For that, we need to know how many dynamic relocs we will have. @@ -558,6 +578,10 @@ SymbolBody &Body = File.getRelocTargetSym(RI); uint32_t Type = RI.getType(Config->Mips64EL); + // We only report undefined symbols if they are referenced somewhere in the code. + if (!Body.isLocal() && Body.isUndefined() && !Body.symbol()->isWeak()) + reportUndefined(Body); + RelExpr Expr = Target->getRelExpr(Type, Body); bool Preemptible = isPreemptible(Body, Type); Expr = adjustExpr(File, Body, IsWrite, Expr, Type, Buf + RI.r_offset); Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -307,25 +307,6 @@ error(EC, "failed to write to the output file"); } -template static void reportUndefined(SymbolBody *Sym) { - if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore) - return; - - if (Config->Shared && Sym->symbol()->Visibility == STV_DEFAULT && - Config->UnresolvedSymbols != UnresolvedPolicy::NoUndef) - return; - - std::string Msg = "undefined symbol: "; - Msg += Config->Demangle ? demangle(Sym->getName()) : Sym->getName().str(); - - if (Sym->File) - Msg += " in " + getFilename(Sym->File); - if (Config->UnresolvedSymbols == UnresolvedPolicy::Warn) - warn(Msg); - else - error(Msg); -} - template static bool shouldKeepInSymtab(InputSectionBase *Sec, StringRef SymName, const SymbolBody &B) { @@ -819,11 +800,6 @@ for (Symbol *S : Symtab::X->getSymbols()) { SymbolBody *Body = S->body(); - // We only report undefined symbols in regular objects. This means that we - // will accept an undefined reference in bitcode if it can be optimized out. - if (S->IsUsedInRegularObj && Body->isUndefined() && !S->isWeak()) - reportUndefined(Body); - if (!includeInSymtab(*Body)) continue; if (Out::SymTab) Index: lld/trunk/test/ELF/Inputs/use-bar.s =================================================================== --- lld/trunk/test/ELF/Inputs/use-bar.s +++ lld/trunk/test/ELF/Inputs/use-bar.s @@ -0,0 +1,2 @@ +.section .bar,"a" + .quad _bar Index: lld/trunk/test/ELF/libsearch.s =================================================================== --- lld/trunk/test/ELF/libsearch.s +++ lld/trunk/test/ELF/libsearch.s @@ -3,6 +3,8 @@ // RUN: %p/Inputs/libsearch-dyn.s -o %tdyn.o // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ // RUN: %p/Inputs/libsearch-st.s -o %tst.o +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +// RUN: %p/Inputs/use-bar.s -o %tbar.o // RUN: mkdir -p %t.dir // RUN: ld.lld -shared %tdyn.o -o %t.dir/libls.so // RUN: cp -f %t.dir/libls.so %t.dir/libls2.so @@ -15,8 +17,10 @@ // RUN: | FileCheck --check-prefix=NOLIBRARY %s // NOLIBRARY: missing arg value for "-l", expected 1 argument. +// Should link normally, because _bar is not used +// RUN: ld.lld -o %t3 %t.o // Should not link because of undefined symbol _bar -// RUN: not ld.lld -o %t3 %t.o 2>&1 \ +// RUN: not ld.lld -o %t3 %t.o %tbar.o 2>&1 \ // RUN: | FileCheck --check-prefix=UNDEFINED %s // UNDEFINED: undefined symbol: _bar Index: lld/trunk/test/ELF/linkerscript/edata-etext.s =================================================================== --- lld/trunk/test/ELF/linkerscript/edata-etext.s +++ lld/trunk/test/ELF/linkerscript/edata-etext.s @@ -3,8 +3,8 @@ # RUN: echo "SECTIONS { }" > %t.script # RUN: not ld.lld %t.o -script %t.script -o %t 2>&1 | FileCheck %s # CHECK: undefined symbol: _edata -# CHECK: undefined symbol: _end # CHECK: undefined symbol: _etext +# CHECK: undefined symbol: _end .global _start,_end,_etext,_edata .text Index: lld/trunk/test/ELF/sysroot.s =================================================================== --- lld/trunk/test/ELF/sysroot.s +++ lld/trunk/test/ELF/sysroot.s @@ -34,3 +34,4 @@ .globl _start,_bar _start: + call _bar Index: lld/trunk/test/ELF/undef-shared.s =================================================================== --- lld/trunk/test/ELF/undef-shared.s +++ lld/trunk/test/ELF/undef-shared.s @@ -12,3 +12,8 @@ # CHECK: undefined symbol: protected in {{.*}} .global protected .protected protected + +.section .data, "a" + .quad hidden + .quad internal + .quad protected Index: lld/trunk/test/ELF/undef.s =================================================================== --- lld/trunk/test/ELF/undef.s +++ lld/trunk/test/ELF/undef.s @@ -4,9 +4,9 @@ # RUN: llvm-ar rc %t2.a %t2.o # RUN: not ld.lld %t.o %t2.a -o %t.exe 2>&1 | FileCheck %s # RUN: not ld.lld -pie %t.o %t2.a -o %t.exe 2>&1 | FileCheck %s -# CHECK: undefined symbol: foo(int) in -# CHECK: undefined symbol: bar in # CHECK: undefined symbol: foo in +# CHECK: undefined symbol: bar in +# CHECK: undefined symbol: foo(int) in # CHECK: undefined symbol: zed2 in {{.*}}2.a({{.*}}.o) # RUN: not ld.lld %t.o %t2.a -o %t.exe -no-demangle 2>&1 | \