Index: test/ELF/trace.s =================================================================== --- test/ELF/trace.s +++ test/ELF/trace.s @@ -6,4 +6,4 @@ # CHECK: {{.*}}.foo.o ## Check --trace alias -# RUN: ld.lld -shared %t.foo.o -o %t.so -t 2>&1 | FileCheck %s +# RUN: ld.lld -shared %t.foo.o -o %t.so --trace 2>&1 | FileCheck %s Index: test/wasm/trace-symbol.ll =================================================================== --- /dev/null +++ test/wasm/trace-symbol.ll @@ -0,0 +1,20 @@ +; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o +; RUN: llc -filetype=obj %p/Inputs/start.ll -o %t.start.o +; RUN: wasm-ld -o %t.wasm %t.start.o %t.ret32.o -y ret32 -y _start 2>&1 | FileCheck %s -check-prefixes=RET32,START + +; check alias +; RUN: wasm-ld -o %t.wasm %t.start.o %t.ret32.o -trace-symbol=ret32 2>&1 | FileCheck %s -check-prefixes=RET32,NOTSTART + +target triple = "wasm32-unknown-unknown" + +declare i32 @ret32() + +define void @_start() { +entry: + %call1 = call i32 @ret32() + ret void +} + +; NOTSTART-NOT: definition of _start +; START: .start.o: definition of _start +; RET32: .ret32.o: definition of ret32 Index: test/wasm/trace.test =================================================================== --- /dev/null +++ test/wasm/trace.test @@ -0,0 +1,8 @@ +RUN: llc -filetype=obj %p/Inputs/start.ll -o %t.foo.o + +# Check -t +RUN: wasm-ld %t.foo.o -o out.wasm -t 2>&1 | FileCheck %s +CHECK: {{.*}}.foo.o + +# Check --trace alias +RUN: wasm-ld %t.foo.o -o out.wasm --trace 2>&1 | FileCheck %s Index: wasm/Config.h =================================================================== --- wasm/Config.h +++ wasm/Config.h @@ -38,6 +38,7 @@ bool StripAll; bool StripDebug; bool StackFirst; + bool Trace; uint32_t GlobalBase; uint32_t InitialMemory; uint32_t MaxMemory; Index: wasm/Driver.cpp =================================================================== --- wasm/Driver.cpp +++ wasm/Driver.cpp @@ -371,6 +371,7 @@ Config->StripAll = Args.hasArg(OPT_strip_all); Config->StripDebug = Args.hasArg(OPT_strip_debug); Config->StackFirst = Args.hasArg(OPT_stack_first); + Config->Trace = Args.hasArg(OPT_trace); Config->ThinLTOCacheDir = Args.getLastArgValue(OPT_thinlto_cache_dir); Config->ThinLTOCachePolicy = CHECK( parseCachePruningPolicy(Args.getLastArgValue(OPT_thinlto_cache_policy)), @@ -556,6 +557,10 @@ Config->AllowUndefined = true; } + // Handle --trace-symbol. + for (auto *Arg : Args.filtered(OPT_trace_symbol)) + Symtab->trace(Arg->getValue()); + if (!Config->Relocatable) createSyntheticSymbols(); Index: wasm/Options.td =================================================================== --- wasm/Options.td +++ wasm/Options.td @@ -93,6 +93,10 @@ def threads: F<"threads">, HelpText<"Run the linker multi-threaded">; +def trace: F<"trace">, HelpText<"Print the names of the input files">; + +defm trace_symbol: Eq<"trace-symbol", "Trace references to symbols">; + defm undefined: Eq<"undefined", "Force undefined symbol during linking">; def v: Flag<["-"], "v">, HelpText<"Display the version number">; @@ -160,6 +164,8 @@ def: Flag<["-"], "r">, Alias; def: Flag<["-"], "s">, Alias, HelpText<"Alias for --strip-all">; def: Flag<["-"], "S">, Alias, HelpText<"Alias for --strip-debug">; +def: Flag<["-"], "t">, Alias, HelpText<"Alias for --trace">; +def: JoinedOrSeparate<["-"], "y">, Alias, HelpText<"Alias for --trace-symbol">; def: JoinedOrSeparate<["-"], "u">, Alias; // LTO-related options. Index: wasm/SymbolTable.h =================================================================== --- wasm/SymbolTable.h +++ wasm/SymbolTable.h @@ -46,8 +46,11 @@ void reportRemainingUndefines(); ArrayRef getSymbols() const { return SymVector; } + Symbol *find(StringRef Name); + void trace(StringRef Name); + Symbol *addDefinedFunction(StringRef Name, uint32_t Flags, InputFile *File, InputFunction *Function); Symbol *addDefinedData(StringRef Name, uint32_t Flags, InputFile *File, @@ -82,6 +85,10 @@ llvm::DenseSet Comdats; + StringRef TraceSymbol; + + llvm::StringSet<> TraceSymbols; + // For LTO. std::unique_ptr LTO; }; Index: wasm/SymbolTable.cpp =================================================================== --- wasm/SymbolTable.cpp +++ wasm/SymbolTable.cpp @@ -28,6 +28,8 @@ void SymbolTable::addFile(InputFile *File) { log("Processing: " + toString(File)); + if (Config->Trace) + message(toString(File)); File->parse(); // LLVM bitcode file @@ -84,6 +86,8 @@ Sym->IsUsedInRegularObj = false; SymVector.emplace_back(Sym); Inserted = true; + if (TraceSymbols.count(Name) != 0) + Sym->Traced = true; } if (!File || File->kind() == InputFile::ObjectKind) Sym->IsUsedInRegularObj = true; @@ -409,3 +413,9 @@ bool SymbolTable::addComdat(StringRef Name) { return Comdats.insert(CachedHashStringRef(Name)).second; } + +// Set a flag for --trace-symbol so that we can print out a log message +// if a new symbol with the same name is inserted into the symbol table. +void SymbolTable::trace(StringRef Name) { + TraceSymbols.insert(Name); +} Index: wasm/Symbols.h =================================================================== --- wasm/Symbols.h +++ wasm/Symbols.h @@ -100,10 +100,14 @@ unsigned IsUsedInRegularObj : 1; unsigned ForceExport : 1; + // True if this symbol is specified by --trace-symbol option. + unsigned Traced : 1; + protected: Symbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F) - : IsUsedInRegularObj(false), ForceExport(false), Name(Name), - SymbolKind(K), Flags(Flags), File(F), Referenced(!Config->GcSections) {} + : IsUsedInRegularObj(false), ForceExport(false), Traced(false), + Name(Name), SymbolKind(K), Flags(Flags), File(F), + Referenced(!Config->GcSections) {} StringRef Name; Kind SymbolKind; @@ -402,6 +406,8 @@ alignas(SectionSymbol) char I[sizeof(SectionSymbol)]; }; +void printTraceSymbol(Symbol *Sym); + template T *replaceSymbol(Symbol *S, ArgT &&... Arg) { static_assert(std::is_trivially_destructible(), @@ -417,6 +423,13 @@ T *S2 = new (S) T(std::forward(Arg)...); S2->IsUsedInRegularObj = SymCopy.IsUsedInRegularObj; S2->ForceExport = SymCopy.ForceExport; + S2->Traced = SymCopy.Traced; + + // Print out a log message if --trace-symbol was specified. + // This is for debugging. + if (S2->Traced) + printTraceSymbol(S2); + return S2; } Index: wasm/Symbols.cpp =================================================================== --- wasm/Symbols.cpp +++ wasm/Symbols.cpp @@ -293,3 +293,16 @@ } llvm_unreachable("invalid symbol kind"); } + +// Print out a log message for --trace-symbol. +void lld::wasm::printTraceSymbol(Symbol *Sym) { + std::string S; + if (Sym->isUndefined()) + S = ": reference to "; + else if (Sym->isLazy()) + S = ": lazy definition of "; + else + S = ": definition of "; + + message(toString(Sym->getFile()) + S + Sym->getName()); +}