Coverage Report

Created: 2018-01-17 17:22

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/ELF/MapFile.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- MapFile.cpp --------------------------------------------------------===//
2
//
3
//                             The LLVM Linker
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
// This file implements the -Map option. It shows lists in order and
11
// hierarchically the output sections, input sections, input files and
12
// symbol:
13
//
14
//   Address  Size     Align Out     In      Symbol
15
//   00201000 00000015     4 .text
16
//   00201000 0000000e     4         test.o:(.text)
17
//   0020100e 00000000     0                 local
18
//   00201005 00000000     0                 f(int)
19
//
20
//===----------------------------------------------------------------------===//
21
22
#include "MapFile.h"
23
#include "InputFiles.h"
24
#include "LinkerScript.h"
25
#include "OutputSections.h"
26
#include "Strings.h"
27
#include "SymbolTable.h"
28
#include "Symbols.h"
29
#include "SyntheticSections.h"
30
#include "lld/Common/Threads.h"
31
#include "llvm/Support/raw_ostream.h"
32
33
using namespace llvm;
34
using namespace llvm::object;
35
36
using namespace lld;
37
using namespace lld::elf;
38
39
typedef DenseMap<const SectionBase *, SmallVector<Symbol *, 4>> SymbolMapTy;
40
41
// Print out the first three columns of a line.
42
static void writeHeader(raw_ostream &OS, uint64_t Addr, uint64_t Size,
43
                        uint64_t Align) {
44
  int W = Config->Is64 ? 16 : 8;
45
  OS << format("%0*llx %0*llx %5lld ", W, Addr, W, Size, Align);
46
}
47
48
static std::string indent(int Depth) { return std::string(Depth * 8, ' '); }
49
50
// Returns a list of all symbols that we want to print out.
51
static std::vector<Symbol *> getSymbols() {
52
  std::vector<Symbol *> V;
53
  for (InputFile *File : ObjectFiles) {
54
    for (Symbol *B : File->getSymbols()) {
55
      if (auto *SS = dyn_cast<SharedSymbol>(B))
56
        if (SS->CopyRelSec || SS->NeedsPltAddr)
57
          V.push_back(SS);
58
      if (auto *DR = dyn_cast<Defined>(B))
59
        if (DR->File == File && !DR->isSection() && DR->Section &&
60
            DR->Section->Live)
61
          V.push_back(DR);
62
    }
63
  }
64
  return V;
65
}
66
67
// Returns a map from sections to their symbols.
68
6
static SymbolMapTy getSectionSyms(ArrayRef<Symbol *> Syms) {
69
6
  SymbolMapTy Ret;
70
43
  for (Symbol *S : Syms) {
71
43
    if (auto *DR = dyn_cast<Defined>(S)) {
72
29
      Ret[DR->Section].push_back(S);
73
29
      continue;
74
29
    }
75
14
76
14
    SharedSymbol *SS = cast<SharedSymbol>(S);
77
14
    if (SS->CopyRelSec)
78
8
      Ret[SS->CopyRelSec].push_back(S);
79
6
    else
80
6
      Ret[InX::Plt].push_back(S);
81
14
  }
82
6
83
6
  // Sort symbols by address. We want to print out symbols in the
84
6
  // order in the output file rather than the order they appeared
85
6
  // in the input files.
86
30
  for (auto &It : Ret) {
87
30
    SmallVectorImpl<Symbol *> &V = It.second;
88
30
    std::sort(V.begin(), V.end(),
89
30
              [](Symbol *A, Symbol *B) 
{ return A->getVA() < B->getVA(); }13
);
90
30
  }
91
6
  return Ret;
92
6
}
93
94
// Construct a map from symbols to their stringified representations.
95
// Demangling symbols (which is what toString() does) is slow, so
96
// we do that in batch using parallel-for.
97
static DenseMap<Symbol *, std::string>
98
6
getSymbolStrings(ArrayRef<Symbol *> Syms) {
99
6
  std::vector<std::string> Str(Syms.size());
100
43
  parallelForEachN(0, Syms.size(), [&](size_t I) {
101
43
    raw_string_ostream OS(Str[I]);
102
43
    writeHeader(OS, Syms[I]->getVA(), Syms[I]->getSize(), 0);
103
43
    OS << indent(2) << toString(*Syms[I]);
104
43
  });
105
6
106
6
  DenseMap<Symbol *, std::string> Ret;
107
49
  for (size_t I = 0, E = Syms.size(); I < E; 
++I43
)
108
43
    Ret[Syms[I]] = std::move(Str[I]);
109
6
  return Ret;
110
6
}
111
112
1.66k
void elf::writeMapFile() {
113
1.66k
  if (Config->MapFile.empty())
114
1.65k
    return;
115
6
116
6
  // Open a map file for writing.
117
6
  std::error_code EC;
118
6
  raw_fd_ostream OS(Config->MapFile, EC, sys::fs::F_None);
119
6
  if (EC) {
120
0
    error("cannot open " + Config->MapFile + ": " + EC.message());
121
0
    return;
122
0
  }
123
6
124
6
  // Collect symbol info that we want to print out.
125
6
  std::vector<Symbol *> Syms = getSymbols();
126
6
  SymbolMapTy SectionSyms = getSectionSyms(Syms);
127
6
  DenseMap<Symbol *, std::string> SymStr = getSymbolStrings(Syms);
128
6
129
6
  // Print out the header line.
130
6
  int W = Config->Is64 ? 16 : 
80
;
131
6
  OS << left_justify("Address", W) << ' ' << left_justify("Size", W)
132
6
     << " Align Out     In      Symbol\n";
133
6
134
6
  // Print out file contents.
135
72
  for (OutputSection *OSec : OutputSections) {
136
72
    writeHeader(OS, OSec->Addr, OSec->Size, OSec->Alignment);
137
72
    OS << OSec->Name << '\n';
138
72
139
72
    // Dump symbols for each input section.
140
72
    for (BaseCommand *Base : OSec->SectionCommands) {
141
72
      auto *ISD = dyn_cast<InputSectionDescription>(Base);
142
72
      if (!ISD)
143
0
        continue;
144
90
      
for (InputSection *IS : ISD->Sections)72
{
145
90
        writeHeader(OS, OSec->Addr + IS->OutSecOff, IS->getSize(),
146
90
                    IS->Alignment);
147
90
        OS << indent(1) << toString(IS) << '\n';
148
90
        for (Symbol *Sym : SectionSyms[IS])
149
43
          OS << SymStr[Sym] << '\n';
150
90
      }
151
72
    }
152
72
  }
153
6
}