1 //===- MapFile.cpp --------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the -Map option. It shows lists in order and
10 // hierarchically the output sections, input sections, input files and
11 // symbol:
12 //
13 // Address Size Align Out In Symbol
14 // 00201000 00000015 4 .text
15 // 00201000 0000000e 4 test.o:(.text)
16 // 0020100e 00000000 0 local
17 // 00201005 00000000 0 f(int)
18 //
19 //===----------------------------------------------------------------------===//
20
21 #include "MapFile.h"
22 #include "InputFiles.h"
23 #include "LinkerScript.h"
24 #include "OutputSections.h"
25 #include "Symbols.h"
26 #include "SyntheticSections.h"
27 #include "llvm/ADT/MapVector.h"
28 #include "llvm/ADT/SetVector.h"
29 #include "llvm/ADT/SmallPtrSet.h"
30 #include "llvm/Support/Parallel.h"
31 #include "llvm/Support/TimeProfiler.h"
32 #include "llvm/Support/raw_ostream.h"
33
34 using namespace llvm;
35 using namespace llvm::object;
36 using namespace lld;
37 using namespace lld::elf;
38
39 using SymbolMapTy = DenseMap<const SectionBase *,
40 SmallVector<std::pair<Defined *, uint64_t>, 0>>;
41
42 static constexpr char indent8[] = " "; // 8 spaces
43 static constexpr char indent16[] = " "; // 16 spaces
44
45 // Print out the first three columns of a line.
writeHeader(Ctx & ctx,raw_ostream & os,uint64_t vma,uint64_t lma,uint64_t size,uint64_t align)46 static void writeHeader(Ctx &ctx, raw_ostream &os, uint64_t vma, uint64_t lma,
47 uint64_t size, uint64_t align) {
48 if (ctx.arg.is64)
49 os << format("%16llx %16llx %8llx %5lld ", vma, lma, size, align);
50 else
51 os << format("%8llx %8llx %8llx %5lld ", vma, lma, size, align);
52 }
53
54 // Returns a list of all symbols that we want to print out.
getSymbols(Ctx & ctx)55 static std::vector<Defined *> getSymbols(Ctx &ctx) {
56 std::vector<Defined *> v;
57 for (ELFFileBase *file : ctx.objectFiles)
58 for (Symbol *b : file->getSymbols())
59 if (auto *dr = dyn_cast<Defined>(b))
60 if (!dr->isSection() && dr->section && dr->section->isLive() &&
61 (dr->file == file || dr->hasFlag(NEEDS_COPY) ||
62 (isa<SyntheticSection>(dr->section) &&
63 cast<SyntheticSection>(dr->section)->bss)))
64 v.push_back(dr);
65 return v;
66 }
67
68 // Returns a map from sections to their symbols.
getSectionSyms(Ctx & ctx,ArrayRef<Defined * > syms)69 static SymbolMapTy getSectionSyms(Ctx &ctx, ArrayRef<Defined *> syms) {
70 SymbolMapTy ret;
71 for (Defined *dr : syms)
72 ret[dr->section].emplace_back(dr, dr->getVA(ctx));
73
74 // Sort symbols by address. We want to print out symbols in the
75 // order in the output file rather than the order they appeared
76 // in the input files.
77 SmallPtrSet<Defined *, 4> set;
78 for (auto &it : ret) {
79 // Deduplicate symbols which need a canonical PLT entry/copy relocation.
80 set.clear();
81 llvm::erase_if(it.second, [&](std::pair<Defined *, uint64_t> a) {
82 return !set.insert(a.first).second;
83 });
84
85 llvm::stable_sort(it.second, llvm::less_second());
86 }
87 return ret;
88 }
89
90 // Construct a map from symbols to their stringified representations.
91 // Demangling symbols (which is what toStr(ctx, ) does) is slow, so
92 // we do that in batch using parallel-for.
93 static DenseMap<Symbol *, std::string>
getSymbolStrings(Ctx & ctx,ArrayRef<Defined * > syms)94 getSymbolStrings(Ctx &ctx, ArrayRef<Defined *> syms) {
95 auto strs = std::make_unique<std::string[]>(syms.size());
96 parallelFor(0, syms.size(), [&](size_t i) {
97 raw_string_ostream os(strs[i]);
98 OutputSection *osec = syms[i]->getOutputSection();
99 uint64_t vma = syms[i]->getVA(ctx);
100 uint64_t lma = osec ? osec->getLMA() + vma - osec->getVA(0) : 0;
101 writeHeader(ctx, os, vma, lma, syms[i]->getSize(), 1);
102 os << indent16 << toStr(ctx, *syms[i]);
103 });
104
105 DenseMap<Symbol *, std::string> ret;
106 for (size_t i = 0, e = syms.size(); i < e; ++i)
107 ret[syms[i]] = std::move(strs[i]);
108 return ret;
109 }
110
111 // Print .eh_frame contents. Since the section consists of EhSectionPieces,
112 // we need a specialized printer for that section.
113 //
114 // .eh_frame tend to contain a lot of section pieces that are contiguous
115 // both in input file and output file. Such pieces are squashed before
116 // being displayed to make output compact.
printEhFrame(Ctx & ctx,raw_ostream & os,const EhFrameSection * sec)117 static void printEhFrame(Ctx &ctx, raw_ostream &os, const EhFrameSection *sec) {
118 std::vector<EhSectionPiece> pieces;
119
120 auto add = [&](const EhSectionPiece &p) {
121 // If P is adjacent to Last, squash the two.
122 if (!pieces.empty()) {
123 EhSectionPiece &last = pieces.back();
124 if (last.sec == p.sec && last.inputOff + last.size == p.inputOff &&
125 last.outputOff + last.size == (unsigned)p.outputOff) {
126 last.size += p.size;
127 return;
128 }
129 }
130 pieces.push_back(p);
131 };
132
133 // Gather section pieces.
134 for (const CieRecord *rec : sec->getCieRecords()) {
135 add(*rec->cie);
136 for (const EhSectionPiece *fde : rec->fdes)
137 add(*fde);
138 }
139
140 // Print out section pieces.
141 const OutputSection *osec = sec->getOutputSection();
142 for (EhSectionPiece &p : pieces) {
143 writeHeader(ctx, os, osec->addr + p.outputOff, osec->getLMA() + p.outputOff,
144 p.size, 1);
145 os << indent8 << toStr(ctx, p.sec->file) << ":(" << p.sec->name << "+0x"
146 << Twine::utohexstr(p.inputOff) + ")\n";
147 }
148 }
149
writeMapFile(Ctx & ctx,raw_fd_ostream & os)150 static void writeMapFile(Ctx &ctx, raw_fd_ostream &os) {
151 // Collect symbol info that we want to print out.
152 std::vector<Defined *> syms = getSymbols(ctx);
153 SymbolMapTy sectionSyms = getSectionSyms(ctx, syms);
154 DenseMap<Symbol *, std::string> symStr = getSymbolStrings(ctx, syms);
155
156 // Print out the header line.
157 int w = ctx.arg.is64 ? 16 : 8;
158 os << right_justify("VMA", w) << ' ' << right_justify("LMA", w)
159 << " Size Align Out In Symbol\n";
160
161 OutputSection *osec = nullptr;
162 for (SectionCommand *cmd : ctx.script->sectionCommands) {
163 if (auto *assign = dyn_cast<SymbolAssignment>(cmd)) {
164 if (assign->provide && !assign->sym)
165 continue;
166 uint64_t lma = osec ? osec->getLMA() + assign->addr - osec->getVA(0) : 0;
167 writeHeader(ctx, os, assign->addr, lma, assign->size, 1);
168 os << assign->commandString << '\n';
169 continue;
170 }
171 if (isa<SectionClassDesc>(cmd))
172 continue;
173
174 osec = &cast<OutputDesc>(cmd)->osec;
175 writeHeader(ctx, os, osec->addr, osec->getLMA(), osec->size,
176 osec->addralign);
177 os << osec->name << '\n';
178
179 // Dump symbols for each input section.
180 for (SectionCommand *subCmd : osec->commands) {
181 if (auto *isd = dyn_cast<InputSectionDescription>(subCmd)) {
182 for (InputSection *isec : isd->sections) {
183 if (auto *ehSec = dyn_cast<EhFrameSection>(isec)) {
184 printEhFrame(ctx, os, ehSec);
185 continue;
186 }
187
188 writeHeader(ctx, os, isec->getVA(), osec->getLMA() + isec->outSecOff,
189 isec->getSize(), isec->addralign);
190 os << indent8 << toStr(ctx, isec) << '\n';
191 for (Symbol *sym : llvm::make_first_range(sectionSyms[isec]))
192 os << symStr[sym] << '\n';
193 }
194 continue;
195 }
196
197 if (auto *data = dyn_cast<ByteCommand>(subCmd)) {
198 writeHeader(ctx, os, osec->addr + data->offset,
199 osec->getLMA() + data->offset, data->size, 1);
200 os << indent8 << data->commandString << '\n';
201 continue;
202 }
203
204 if (auto *assign = dyn_cast<SymbolAssignment>(subCmd)) {
205 if (assign->provide && !assign->sym)
206 continue;
207 writeHeader(ctx, os, assign->addr,
208 osec->getLMA() + assign->addr - osec->getVA(0),
209 assign->size, 1);
210 os << indent8 << assign->commandString << '\n';
211 continue;
212 }
213 }
214 }
215 }
216
217 // Output a cross reference table to stdout. This is for --cref.
218 //
219 // For each global symbol, we print out a file that defines the symbol
220 // followed by files that uses that symbol. Here is an example.
221 //
222 // strlen /lib/x86_64-linux-gnu/libc.so.6
223 // tools/lld/tools/lld/CMakeFiles/lld.dir/lld.cpp.o
224 // lib/libLLVMSupport.a(PrettyStackTrace.cpp.o)
225 //
226 // In this case, strlen is defined by libc.so.6 and used by other two
227 // files.
writeCref(Ctx & ctx,raw_fd_ostream & os)228 static void writeCref(Ctx &ctx, raw_fd_ostream &os) {
229 // Collect symbols and files.
230 MapVector<Symbol *, SetVector<InputFile *>> map;
231 for (ELFFileBase *file : ctx.objectFiles) {
232 for (Symbol *sym : file->getSymbols()) {
233 if (isa<SharedSymbol>(sym))
234 map[sym].insert(file);
235 if (auto *d = dyn_cast<Defined>(sym))
236 if (!d->isLocal())
237 map[d].insert(file);
238 }
239 }
240
241 auto print = [&](StringRef a, StringRef b) {
242 os << left_justify(a, 49) << ' ' << b << '\n';
243 };
244
245 // Print a blank line and a header. The format matches GNU ld.
246 os << "\nCross Reference Table\n\n";
247 print("Symbol", "File");
248
249 // Print out a table.
250 for (auto kv : map) {
251 Symbol *sym = kv.first;
252 SetVector<InputFile *> &files = kv.second;
253
254 print(toStr(ctx, *sym), toStr(ctx, sym->file));
255 for (InputFile *file : files)
256 if (file != sym->file)
257 print("", toStr(ctx, file));
258 }
259 }
260
writeMapAndCref(Ctx & ctx)261 void elf::writeMapAndCref(Ctx &ctx) {
262 if (ctx.arg.mapFile.empty() && !ctx.arg.cref)
263 return;
264
265 llvm::TimeTraceScope timeScope("Write map file");
266
267 // Open a map file for writing.
268 std::error_code ec;
269 StringRef mapFile = ctx.arg.mapFile.empty() ? "-" : ctx.arg.mapFile;
270 raw_fd_ostream os = ctx.openAuxiliaryFile(mapFile, ec);
271 if (ec) {
272 ErrAlways(ctx) << "cannot open " << mapFile << ": " << ec.message();
273 return;
274 }
275
276 if (!ctx.arg.mapFile.empty())
277 writeMapFile(ctx, os);
278 if (ctx.arg.cref)
279 writeCref(ctx, os);
280 }
281