Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -12,6 +12,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Support/ELF.h" #include @@ -64,6 +65,7 @@ std::vector SearchPaths; std::vector Undefined; std::vector VersionScriptGlobals; + llvm::StringSet<> TraceSymbol; std::vector BuildIdVector; bool AllowMultipleDefinition; bool AsNeeded = false; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -417,6 +417,9 @@ if (Optional Buffer = readFile(Arg->getValue())) parseVersionScript(*Buffer); } + + for (auto *Arg : Args.filtered(OPT_trace_symbol)) + Config->TraceSymbol.insert(Arg->getValue()); } void LinkerDriver::createFiles(opt::InputArgList &Args) { Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -51,6 +51,9 @@ StringRef getName() const { return MB.getBufferIdentifier(); } MemoryBufferRef MB; + void traceDefined(StringRef &Name); + void traceUndefined(StringRef &Name); + // Filename of .a which contained this file. If this file was // not in an archive file, it is the empty string. We use this // string for creating error messages. Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -313,6 +313,34 @@ return new (IAlloc.Allocate()) InputSection(this, &Sec); } +// Print the module names which define the notified +// symbols provided through -y or --trace-symbol option. +void InputFile::traceDefined(StringRef &Name) { + if (Config->TraceSymbol.count(Name)) { + std::string Msg; + if (!ArchiveName.empty()) + Msg += ArchiveName.str() + "(" + this->getName().str() + ")"; + else + Msg += this->getName().str(); + Msg += ": definition of " + Name.str(); + llvm::outs() << Msg << "\n"; + } +} + +// Print the module names which reference the notified +// symbols provided through -y or --trace-symbol option. +void InputFile::traceUndefined(StringRef &Name) { + if (Config->TraceSymbol.count(Name)) { + std::string Msg; + if (!ArchiveName.empty()) + Msg += ArchiveName.str() + "(" + this->getName().str() + ")"; + else + Msg += this->getName().str(); + Msg += ": reference to " + Name.str(); + llvm::outs() << Msg << "\n"; + } +} + template void elf::ObjectFile::initializeSymbols() { this->initStringTable(); Elf_Sym_Range Syms = this->getElfSymbols(false); @@ -350,11 +378,13 @@ switch (Sym->st_shndx) { case SHN_UNDEF: + InputFile::traceUndefined(Name); return elf::Symtab::X ->addUndefined(Name, Binding, Sym->st_other, Sym->getType(), /*CanOmitFromDynSym*/ false, this) ->body(); case SHN_COMMON: + InputFile::traceDefined(Name); return elf::Symtab::X ->addCommon(Name, Sym->st_size, Sym->st_value, Binding, Sym->st_other, Sym->getType(), this) @@ -525,9 +555,12 @@ StringRef Name = check(Sym.getName(this->StringTable)); if (Sym.isUndefined()) { + InputFile::traceUndefined(Name); Undefs.push_back(Name); continue; } + else if (Sym.isDefined()) + InputFile::traceDefined(Name); if (Versym) { // Ignore local symbols and non-default versions. Index: ELF/Options.td =================================================================== --- ELF/Options.td +++ ELF/Options.td @@ -122,6 +122,9 @@ def z : JoinedOrSeparate<["-"], "z">, MetaVarName<"