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