[ELF] --cref: If -Map is specified, print to the map file

PR48282: This behavior matches GNU ld and gold.

Reviewed By: markj

Differential Revision: https://reviews.llvm.org/D114663
This commit is contained in:
Fangrui Song 2021-11-29 14:14:53 -08:00
parent 99f8b795cc
commit 1ce51a5f35
7 changed files with 54 additions and 31 deletions

View File

@ -139,20 +139,7 @@ static void printEhFrame(raw_ostream &os, const EhFrameSection *sec) {
}
}
void elf::writeMapFile() {
if (config->mapFile.empty())
return;
llvm::TimeTraceScope timeScope("Write map file");
// Open a map file for writing.
std::error_code ec;
raw_fd_ostream os(config->mapFile, ec, sys::fs::OF_None);
if (ec) {
error("cannot open " + config->mapFile + ": " + ec.message());
return;
}
static void writeMapFile(raw_fd_ostream &os) {
// Collect symbol info that we want to print out.
std::vector<Defined *> syms = getSymbols();
SymbolMapTy sectionSyms = getSectionSyms(syms);
@ -235,10 +222,6 @@ void elf::writeWhyExtract() {
}
}
static void print(StringRef a, StringRef b) {
lld::outs() << left_justify(a, 49) << " " << b << "\n";
}
// Output a cross reference table to stdout. This is for --cref.
//
// For each global symbol, we print out a file that defines the symbol
@ -250,10 +233,7 @@ static void print(StringRef a, StringRef b) {
//
// In this case, strlen is defined by libc.so.6 and used by other two
// files.
void elf::writeCrossReferenceTable() {
if (!config->cref)
return;
static void writeCref(raw_fd_ostream &os) {
// Collect symbols and files.
MapVector<Symbol *, SetVector<InputFile *>> map;
for (InputFile *file : objectFiles) {
@ -266,8 +246,12 @@ void elf::writeCrossReferenceTable() {
}
}
// Print out a header.
lld::outs() << "Cross Reference Table\n\n";
auto print = [&](StringRef a, StringRef b) {
os << left_justify(a, 49) << ' ' << b << '\n';
};
// Print a blank line and a header. The format matches GNU ld.
os << "\nCross Reference Table\n\n";
print("Symbol", "File");
// Print out a table.
@ -282,6 +266,27 @@ void elf::writeCrossReferenceTable() {
}
}
void elf::writeMapAndCref() {
if (config->mapFile.empty() && !config->cref)
return;
llvm::TimeTraceScope timeScope("Write map file");
// Open a map file for writing.
std::error_code ec;
StringRef mapFile = config->mapFile.empty() ? "-" : config->mapFile;
raw_fd_ostream os(mapFile, ec, sys::fs::OF_None);
if (ec) {
error("cannot open " + mapFile + ": " + ec.message());
return;
}
if (!config->mapFile.empty())
writeMapFile(os);
if (config->cref)
writeCref(os);
}
void elf::writeArchiveStats() {
if (config->printArchiveStats.empty())
return;

View File

@ -11,9 +11,8 @@
namespace lld {
namespace elf {
void writeMapFile();
void writeMapAndCref();
void writeWhyExtract();
void writeCrossReferenceTable();
void writeArchiveStats();
} // namespace elf
} // namespace lld

View File

@ -129,7 +129,8 @@ def color_diagnostics_eq: J<"color-diagnostics=">,
HelpText<"Use colors in diagnostics (default: auto)">,
MetaVarName<"[auto,always,never]">;
def cref: FF<"cref">, HelpText<"Output cross reference table">;
def cref: FF<"cref">,
HelpText<"Output cross reference table. If -Map is specified, print to the map file">;
defm define_common: B<"define-common",
"Assign space to common symbols",

View File

@ -565,9 +565,8 @@ template <class ELFT> void Writer<ELFT>::run() {
// --print-archive-stats=. Dump them before checkSections() because the files
// may be useful in case checkSections() or openFile() fails, for example, due
// to an erroneous file size.
writeMapFile();
writeMapAndCref();
writeWhyExtract();
writeCrossReferenceTable();
writeArchiveStats();
if (config->checkSections)

View File

@ -31,6 +31,8 @@ ELF Improvements
* ``e_entry`` no longer falls back to the address of ``.text`` if the entry symbol does not exist.
Instead, a value of 0 will be written.
(`D110014 <https://reviews.llvm.org/D110014>`_)
* If ``-Map`` is specified, ``--cref`` will be printted to the specified file.
(`D114663 <https://reviews.llvm.org/D114663>`_)
Architecture specific changes:

View File

@ -141,7 +141,9 @@ you can specify
.Fl O2
to set the compression level to 6.
.It Fl -cref
Output cross reference table.
Output cross reference table. If
.Fl Map
is specified, print to the map file.
.It Fl -define-common , Fl d
Assign space to common symbols.
.It Fl -defsym Ns = Ns Ar symbol Ns = Ns Ar expression

View File

@ -9,7 +9,14 @@
// RUN: ld.lld -shared -o %t1.so %t1.o
// RUN: ld.lld -o /dev/null %t1.so %t2.o %t3.o %t.a --gc-sections --cref | FileCheck -strict-whitespace %s
// CHECK: Symbol File
/// If -Map is specified, print to the map file.
// RUN: ld.lld -o /dev/null %t1.so %t2.o %t3.o %t.a --gc-sections -Map=%t.map --cref
// RUN: FileCheck --input-file=%t.map %s --check-prefix=CHECK2
// CHECK: {{^$}}
// CHECK-NEXT: Cross Reference Table
// CHECK-EMPTY:
// CHECK-NEXT: Symbol File
// CHECK-NEXT: foo {{.*}}1.so
// CHECK-NEXT: {{.*}}2.o
// CHECK-NEXT: {{.*}}3.o
@ -21,6 +28,14 @@
// CHECK-NEXT: {{.*}}3.o
// CHECK-NOT: discarded
// CHECK2: VMA LMA Size Align Out In Symbol
// CHECK2: .strtab
// CHECK2-NEXT: <internal>:(.strtab)
/// There is a blank line before the "Cross Reference Table" header.
// CHECK2-EMPTY:
// CHECK2-NEXT: Cross Reference Table
.global _start, foo, bar, baz, discarded
_start:
call foo