diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -170,6 +170,7 @@ bool pacPlt; bool picThunk; bool pie; + bool printDependencyGraph; bool printGcSections; bool printIcfSections; bool relocatable; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -263,6 +263,7 @@ files.push_back(make(mbref, "", 0)); else files.push_back(createObjectFile(mbref)); + files.back()->onCommandLine = true; break; default: error(path + ": unknown file type"); @@ -872,6 +873,8 @@ config->outputFile = args.getLastArgValue(OPT_o); config->pacPlt = args.hasArg(OPT_pac_plt); config->pie = args.hasFlag(OPT_pie, OPT_no_pie, false); + config->printDependencyGraph = + args.hasFlag(OPT_print_dependency_graph, OPT_no_print_dependency_graph, false); config->printIcfSections = args.hasFlag(OPT_print_icf_sections, OPT_no_print_icf_sections, false); config->printGcSections = @@ -1672,6 +1675,29 @@ #undef HANDLE_LIBCALL }; +// Print out dependencies between files for off-line analysis. +static void dumpSymbols() { + outs() << "# This is a dump of the internal symbol table of the lld linker\n" + << "# when linking '" << config->outputFile << "'.\n#\n" + << "# The format of this file is as follows:\n#\n" + << "# \n#\n" + << "# meaning uses defined by .\n\n"; + + for (InputFile *file : objectFiles) + if (file->onCommandLine) + outs() << "\t" << toString(file) << "\t-\n"; + + for (InputFile *file : objectFiles) { + for (Symbol *sym : file->getSymbols()) { + if (sym->isLocal() || sym->file == file) + continue; + + outs() << toString(file) << "\t" << toString(sym->file) << "\t" + << toString(*sym) << "\n"; + } + } +} + // Do actual linking. Note that when this function is called, // all linker scripts have already been parsed. template void LinkerDriver::link(opt::InputArgList &args) { @@ -1939,6 +1965,9 @@ readCallGraphsFromObjectFiles(); } + if (config->printDependencyGraph) + dumpSymbols(); + // Write the result to the file. writeResult(); } diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -108,6 +108,10 @@ uint8_t osabi = 0; uint8_t abiVersion = 0; + // True if this is an object file and is given directly on the command + // line. False if this file is read from an archive file. + bool onCommandLine; + // Cache for toString(). Only toString() should use this member. mutable std::string toStringCache; diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -286,6 +286,10 @@ "Create a position independent executable", "Do not create a position independent executable (default)">; +defm print_dependency_graph: B<"print-dependency-graph", + "Print out the contents of the linker's internal symbol table", + "Do not print out the dependency graph (default)">; + defm print_gc_sections: B<"print-gc-sections", "List removed unused sections", "Do not list removed unused sections (default)">;