diff options
Diffstat (limited to 'ELF/MapFile.cpp')
-rw-r--r-- | ELF/MapFile.cpp | 165 |
1 files changed, 88 insertions, 77 deletions
diff --git a/ELF/MapFile.cpp b/ELF/MapFile.cpp index 31c8091bb6a1..af5bc3c2c813 100644 --- a/ELF/MapFile.cpp +++ b/ELF/MapFile.cpp @@ -11,19 +11,19 @@ // hierarchically the output sections, input sections, input files and // symbol: // -// Address Size Align Out In File Symbol -// ================================================================= -// 00201000 00000015 4 .text -// 00201000 0000000e 4 .text -// 00201000 0000000e 4 test.o -// 0020100e 00000000 0 local -// 00201005 00000000 0 f(int) +// Address Size Align Out In Symbol +// 00201000 00000015 4 .text +// 00201000 0000000e 4 test.o:(.text) +// 0020100e 00000000 0 local +// 00201005 00000000 0 f(int) // //===----------------------------------------------------------------------===// #include "MapFile.h" #include "InputFiles.h" #include "Strings.h" +#include "SymbolTable.h" +#include "Threads.h" #include "llvm/Support/raw_ostream.h" @@ -33,83 +33,68 @@ using namespace llvm::object; using namespace lld; using namespace lld::elf; -static void writeOutSecLine(raw_fd_ostream &OS, int Width, uint64_t Address, - uint64_t Size, uint64_t Align, StringRef Name) { - OS << format("%0*llx %0*llx %5lld ", Width, Address, Width, Size, Align) - << left_justify(Name, 7); -} - -static void writeInSecLine(raw_fd_ostream &OS, int Width, uint64_t Address, - uint64_t Size, uint64_t Align, StringRef Name) { - // Pass an empty name to align the text to the correct column. - writeOutSecLine(OS, Width, Address, Size, Align, ""); - OS << ' ' << left_justify(Name, 7); -} +typedef DenseMap<const SectionBase *, SmallVector<DefinedRegular *, 4>> + SymbolMapTy; -static void writeFileLine(raw_fd_ostream &OS, int Width, uint64_t Address, - uint64_t Size, uint64_t Align, StringRef Name) { - // Pass an empty name to align the text to the correct column. - writeInSecLine(OS, Width, Address, Size, Align, ""); - OS << ' ' << left_justify(Name, 7); +// Print out the first three columns of a line. +template <class ELFT> +static void writeHeader(raw_ostream &OS, uint64_t Addr, uint64_t Size, + uint64_t Align) { + int W = ELFT::Is64Bits ? 16 : 8; + OS << format("%0*llx %0*llx %5lld ", W, Addr, W, Size, Align); } -static void writeSymbolLine(raw_fd_ostream &OS, int Width, uint64_t Address, - uint64_t Size, StringRef Name) { - // Pass an empty name to align the text to the correct column. - writeFileLine(OS, Width, Address, Size, 0, ""); - OS << ' ' << left_justify(Name, 7); +static std::string indent(int Depth) { return std::string(Depth * 8, ' '); } + +// Returns a list of all symbols that we want to print out. +template <class ELFT> std::vector<DefinedRegular *> getSymbols() { + std::vector<DefinedRegular *> V; + for (elf::ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) + for (SymbolBody *B : File->getSymbols()) + if (B->File == File && !B->isSection()) + if (auto *Sym = dyn_cast<DefinedRegular>(B)) + if (Sym->Section) + V.push_back(Sym); + return V; } +// Returns a map from sections to their symbols. template <class ELFT> -static void writeInputSection(raw_fd_ostream &OS, const InputSection *IS, - StringRef &PrevName) { - int Width = ELFT::Is64Bits ? 16 : 8; - StringRef Name = IS->Name; - if (Name != PrevName) { - writeInSecLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff, IS->getSize(), - IS->Alignment, Name); - OS << '\n'; - PrevName = Name; - } - - elf::ObjectFile<ELFT> *File = IS->template getFile<ELFT>(); - if (!File) - return; - writeFileLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff, IS->getSize(), - IS->Alignment, toString(File)); - OS << '\n'; - - for (SymbolBody *Sym : File->getSymbols()) { - auto *DR = dyn_cast<DefinedRegular>(Sym); - if (!DR) - continue; - if (DR->Section != IS) - continue; - if (DR->isSection()) - continue; - writeSymbolLine(OS, Width, Sym->getVA(), Sym->getSize<ELFT>(), - toString(*Sym)); - OS << '\n'; +SymbolMapTy getSectionSyms(ArrayRef<DefinedRegular *> Syms) { + SymbolMapTy Ret; + for (DefinedRegular *S : Syms) + Ret[S->Section].push_back(S); + + // Sort symbols by address. We want to print out symbols in the + // order in the output file rather than the order they appeared + // in the input files. + for (auto &It : Ret) { + SmallVectorImpl<DefinedRegular *> &V = It.second; + std::sort(V.begin(), V.end(), [](DefinedRegular *A, DefinedRegular *B) { + return A->getVA() < B->getVA(); + }); } + return Ret; } +// Construct a map from symbols to their stringified representations. +// Demangling symbols (which is what toString() does) is slow, so +// we do that in batch using parallel-for. template <class ELFT> -static void writeMapFile2(raw_fd_ostream &OS, - ArrayRef<OutputSection *> OutputSections) { - int Width = ELFT::Is64Bits ? 16 : 8; - - OS << left_justify("Address", Width) << ' ' << left_justify("Size", Width) - << " Align Out In File Symbol\n"; - - for (OutputSection *Sec : OutputSections) { - writeOutSecLine(OS, Width, Sec->Addr, Sec->Size, Sec->Alignment, Sec->Name); - OS << '\n'; - - StringRef PrevName = ""; - for (InputSection *IS : Sec->Sections) { - writeInputSection<ELFT>(OS, IS, PrevName); - } - } +DenseMap<DefinedRegular *, std::string> +getSymbolStrings(ArrayRef<DefinedRegular *> Syms) { + std::vector<std::string> Str(Syms.size()); + parallelFor(0, Syms.size(), [&](size_t I) { + raw_string_ostream OS(Str[I]); + writeHeader<ELFT>(OS, Syms[I]->getVA(), Syms[I]->template getSize<ELFT>(), + 0); + OS << indent(2) << toString(*Syms[I]); + }); + + DenseMap<DefinedRegular *, std::string> Ret; + for (size_t I = 0, E = Syms.size(); I < E; ++I) + Ret[Syms[I]] = std::move(Str[I]); + return Ret; } template <class ELFT> @@ -117,12 +102,38 @@ void elf::writeMapFile(ArrayRef<OutputSection *> OutputSections) { if (Config->MapFile.empty()) return; + // Open a map file for writing. std::error_code EC; raw_fd_ostream OS(Config->MapFile, EC, sys::fs::F_None); - if (EC) + if (EC) { error("cannot open " + Config->MapFile + ": " + EC.message()); - else - writeMapFile2<ELFT>(OS, OutputSections); + return; + } + + // Collect symbol info that we want to print out. + std::vector<DefinedRegular *> Syms = getSymbols<ELFT>(); + SymbolMapTy SectionSyms = getSectionSyms<ELFT>(Syms); + DenseMap<DefinedRegular *, std::string> SymStr = getSymbolStrings<ELFT>(Syms); + + // Print out the header line. + int W = ELFT::Is64Bits ? 16 : 8; + OS << left_justify("Address", W) << ' ' << left_justify("Size", W) + << " Align Out In Symbol\n"; + + // Print out file contents. + for (OutputSection *OSec : OutputSections) { + writeHeader<ELFT>(OS, OSec->Addr, OSec->Size, OSec->Alignment); + OS << OSec->Name << '\n'; + + // Dump symbols for each input section. + for (InputSection *IS : OSec->Sections) { + writeHeader<ELFT>(OS, OSec->Addr + IS->OutSecOff, IS->getSize(), + IS->Alignment); + OS << indent(1) << toString(IS) << '\n'; + for (DefinedRegular *Sym : SectionSyms[IS]) + OS << SymStr[Sym] << '\n'; + } + } } template void elf::writeMapFile<ELF32LE>(ArrayRef<OutputSection *>); |