MapFile.cpp revision 319164
1317025Sdim//===- MapFile.cpp --------------------------------------------------------===// 2317025Sdim// 3317025Sdim// The LLVM Linker 4317025Sdim// 5317025Sdim// This file is distributed under the University of Illinois Open Source 6317025Sdim// License. See LICENSE.TXT for details. 7317025Sdim// 8317025Sdim//===----------------------------------------------------------------------===// 9317025Sdim// 10317025Sdim// This file implements the -Map option. It shows lists in order and 11317025Sdim// hierarchically the output sections, input sections, input files and 12317025Sdim// symbol: 13317025Sdim// 14317778Sdim// Address Size Align Out In Symbol 15317778Sdim// 00201000 00000015 4 .text 16317778Sdim// 00201000 0000000e 4 test.o:(.text) 17317778Sdim// 0020100e 00000000 0 local 18317778Sdim// 00201005 00000000 0 f(int) 19317025Sdim// 20317025Sdim//===----------------------------------------------------------------------===// 21317025Sdim 22317025Sdim#include "MapFile.h" 23317025Sdim#include "InputFiles.h" 24318681Sdim#include "LinkerScript.h" 25318681Sdim#include "OutputSections.h" 26317025Sdim#include "Strings.h" 27317778Sdim#include "SymbolTable.h" 28317778Sdim#include "Threads.h" 29317025Sdim 30317025Sdim#include "llvm/Support/raw_ostream.h" 31317025Sdim 32317025Sdimusing namespace llvm; 33317025Sdimusing namespace llvm::object; 34317025Sdim 35317025Sdimusing namespace lld; 36317025Sdimusing namespace lld::elf; 37317025Sdim 38317778Sdimtypedef DenseMap<const SectionBase *, SmallVector<DefinedRegular *, 4>> 39317778Sdim SymbolMapTy; 40317025Sdim 41317778Sdim// Print out the first three columns of a line. 42317778Sdimtemplate <class ELFT> 43317778Sdimstatic void writeHeader(raw_ostream &OS, uint64_t Addr, uint64_t Size, 44317778Sdim uint64_t Align) { 45317778Sdim int W = ELFT::Is64Bits ? 16 : 8; 46317778Sdim OS << format("%0*llx %0*llx %5lld ", W, Addr, W, Size, Align); 47317025Sdim} 48317025Sdim 49317778Sdimstatic std::string indent(int Depth) { return std::string(Depth * 8, ' '); } 50317025Sdim 51317778Sdim// Returns a list of all symbols that we want to print out. 52317778Sdimtemplate <class ELFT> std::vector<DefinedRegular *> getSymbols() { 53317778Sdim std::vector<DefinedRegular *> V; 54317778Sdim for (elf::ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) 55317778Sdim for (SymbolBody *B : File->getSymbols()) 56317778Sdim if (B->File == File && !B->isSection()) 57317778Sdim if (auto *Sym = dyn_cast<DefinedRegular>(B)) 58317778Sdim if (Sym->Section) 59317778Sdim V.push_back(Sym); 60317778Sdim return V; 61317025Sdim} 62317025Sdim 63317778Sdim// Returns a map from sections to their symbols. 64317025Sdimtemplate <class ELFT> 65317778SdimSymbolMapTy getSectionSyms(ArrayRef<DefinedRegular *> Syms) { 66317778Sdim SymbolMapTy Ret; 67317778Sdim for (DefinedRegular *S : Syms) 68317778Sdim Ret[S->Section].push_back(S); 69317025Sdim 70317778Sdim // Sort symbols by address. We want to print out symbols in the 71317778Sdim // order in the output file rather than the order they appeared 72317778Sdim // in the input files. 73317778Sdim for (auto &It : Ret) { 74317778Sdim SmallVectorImpl<DefinedRegular *> &V = It.second; 75317778Sdim std::sort(V.begin(), V.end(), [](DefinedRegular *A, DefinedRegular *B) { 76317778Sdim return A->getVA() < B->getVA(); 77317778Sdim }); 78317025Sdim } 79317778Sdim return Ret; 80317025Sdim} 81317025Sdim 82317778Sdim// Construct a map from symbols to their stringified representations. 83317778Sdim// Demangling symbols (which is what toString() does) is slow, so 84317778Sdim// we do that in batch using parallel-for. 85317025Sdimtemplate <class ELFT> 86317778SdimDenseMap<DefinedRegular *, std::string> 87317778SdimgetSymbolStrings(ArrayRef<DefinedRegular *> Syms) { 88317778Sdim std::vector<std::string> Str(Syms.size()); 89318384Sdim parallelForEachN(0, Syms.size(), [&](size_t I) { 90317778Sdim raw_string_ostream OS(Str[I]); 91317778Sdim writeHeader<ELFT>(OS, Syms[I]->getVA(), Syms[I]->template getSize<ELFT>(), 92317778Sdim 0); 93317778Sdim OS << indent(2) << toString(*Syms[I]); 94317778Sdim }); 95317025Sdim 96317778Sdim DenseMap<DefinedRegular *, std::string> Ret; 97317778Sdim for (size_t I = 0, E = Syms.size(); I < E; ++I) 98317778Sdim Ret[Syms[I]] = std::move(Str[I]); 99317778Sdim return Ret; 100317025Sdim} 101317025Sdim 102317025Sdimtemplate <class ELFT> 103318681Sdimvoid elf::writeMapFile(llvm::ArrayRef<BaseCommand *> Script) { 104317025Sdim if (Config->MapFile.empty()) 105317025Sdim return; 106317025Sdim 107317778Sdim // Open a map file for writing. 108317025Sdim std::error_code EC; 109317025Sdim raw_fd_ostream OS(Config->MapFile, EC, sys::fs::F_None); 110317778Sdim if (EC) { 111317025Sdim error("cannot open " + Config->MapFile + ": " + EC.message()); 112317778Sdim return; 113317778Sdim } 114317778Sdim 115317778Sdim // Collect symbol info that we want to print out. 116317778Sdim std::vector<DefinedRegular *> Syms = getSymbols<ELFT>(); 117317778Sdim SymbolMapTy SectionSyms = getSectionSyms<ELFT>(Syms); 118317778Sdim DenseMap<DefinedRegular *, std::string> SymStr = getSymbolStrings<ELFT>(Syms); 119317778Sdim 120317778Sdim // Print out the header line. 121317778Sdim int W = ELFT::Is64Bits ? 16 : 8; 122317778Sdim OS << left_justify("Address", W) << ' ' << left_justify("Size", W) 123317778Sdim << " Align Out In Symbol\n"; 124317778Sdim 125317778Sdim // Print out file contents. 126318681Sdim for (BaseCommand *Base : Script) { 127318681Sdim auto *Cmd = dyn_cast<OutputSectionCommand>(Base); 128318681Sdim if (!Cmd) 129318681Sdim continue; 130318681Sdim OutputSection *OSec = Cmd->Sec; 131317778Sdim writeHeader<ELFT>(OS, OSec->Addr, OSec->Size, OSec->Alignment); 132317778Sdim OS << OSec->Name << '\n'; 133317778Sdim 134317778Sdim // Dump symbols for each input section. 135319164Sdim for (BaseCommand *Base : Cmd->Commands) { 136319164Sdim auto *ISD = dyn_cast<InputSectionDescription>(Base); 137319164Sdim if (!ISD) 138319164Sdim continue; 139319164Sdim for (InputSection *IS : ISD->Sections) { 140319164Sdim writeHeader<ELFT>(OS, OSec->Addr + IS->OutSecOff, IS->getSize(), 141319164Sdim IS->Alignment); 142319164Sdim OS << indent(1) << toString(IS) << '\n'; 143319164Sdim for (DefinedRegular *Sym : SectionSyms[IS]) 144319164Sdim OS << SymStr[Sym] << '\n'; 145319164Sdim } 146317778Sdim } 147317778Sdim } 148317025Sdim} 149317025Sdim 150318681Sdimtemplate void elf::writeMapFile<ELF32LE>(ArrayRef<BaseCommand *>); 151318681Sdimtemplate void elf::writeMapFile<ELF32BE>(ArrayRef<BaseCommand *>); 152318681Sdimtemplate void elf::writeMapFile<ELF64LE>(ArrayRef<BaseCommand *>); 153318681Sdimtemplate void elf::writeMapFile<ELF64BE>(ArrayRef<BaseCommand *>); 154