xref: /llvm-project-15.0.7/lld/ELF/MapFile.cpp (revision c5a20b51)
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 "Driver.h"
23 #include "InputFiles.h"
24 #include "LinkerScript.h"
25 #include "OutputSections.h"
26 #include "Symbols.h"
27 #include "SyntheticSections.h"
28 #include "llvm/ADT/MapVector.h"
29 #include "llvm/ADT/SetVector.h"
30 #include "llvm/ADT/SmallPtrSet.h"
31 #include "llvm/Support/FileSystem.h"
32 #include "llvm/Support/Parallel.h"
33 #include "llvm/Support/TimeProfiler.h"
34 #include "llvm/Support/raw_ostream.h"
35 
36 using namespace llvm;
37 using namespace llvm::object;
38 using namespace lld;
39 using namespace lld::elf;
40 
41 using SymbolMapTy = DenseMap<const SectionBase *,
42                              SmallVector<std::pair<Defined *, uint64_t>, 0>>;
43 
44 static constexpr char indent8[] = "        ";          // 8 spaces
45 static constexpr char indent16[] = "                "; // 16 spaces
46 
47 // Print out the first three columns of a line.
48 static void writeHeader(raw_ostream &os, uint64_t vma, uint64_t lma,
49                         uint64_t size, uint64_t align) {
50   if (config->is64)
51     os << format("%16llx %16llx %8llx %5lld ", vma, lma, size, align);
52   else
53     os << format("%8llx %8llx %8llx %5lld ", vma, lma, size, align);
54 }
55 
56 // Returns a list of all symbols that we want to print out.
57 static std::vector<Defined *> getSymbols() {
58   std::vector<Defined *> v;
59   for (ELFFileBase *file : objectFiles)
60     for (Symbol *b : file->getSymbols())
61       if (auto *dr = dyn_cast<Defined>(b))
62         if (!dr->isSection() && dr->section && dr->section->isLive() &&
63             (dr->file == file || dr->needsCopy || dr->section->bss))
64           v.push_back(dr);
65   return v;
66 }
67 
68 // Returns a map from sections to their symbols.
69 static SymbolMapTy getSectionSyms(ArrayRef<Defined *> syms) {
70   SymbolMapTy ret;
71   for (Defined *dr : syms)
72     ret[dr->section].emplace_back(dr, dr->getVA());
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 toString() does) is slow, so
92 // we do that in batch using parallel-for.
93 static DenseMap<Symbol *, std::string>
94 getSymbolStrings(ArrayRef<Defined *> syms) {
95   auto strs = std::make_unique<std::string[]>(syms.size());
96   parallelForEachN(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();
100     uint64_t lma = osec ? osec->getLMA() + vma - osec->getVA(0) : 0;
101     writeHeader(os, vma, lma, syms[i]->getSize(), 1);
102     os << indent16 << toString(*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.
117 static void printEhFrame(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 == 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(os, osec->addr + p.outputOff, osec->getLMA() + p.outputOff,
144                 p.size, 1);
145     os << indent8 << toString(p.sec->file) << ":(" << p.sec->name << "+0x"
146        << Twine::utohexstr(p.inputOff) + ")\n";
147   }
148 }
149 
150 static void writeMapFile(raw_fd_ostream &os) {
151   // Collect symbol info that we want to print out.
152   std::vector<Defined *> syms = getSymbols();
153   SymbolMapTy sectionSyms = getSectionSyms(syms);
154   DenseMap<Symbol *, std::string> symStr = getSymbolStrings(syms);
155 
156   // Print out the header line.
157   int w = config->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 : 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(os, assign->addr, lma, assign->size, 1);
168       os << assign->commandString << '\n';
169       continue;
170     }
171 
172     osec = cast<OutputSection>(cmd);
173     writeHeader(os, osec->addr, osec->getLMA(), osec->size, osec->alignment);
174     os << osec->name << '\n';
175 
176     // Dump symbols for each input section.
177     for (SectionCommand *subCmd : osec->commands) {
178       if (auto *isd = dyn_cast<InputSectionDescription>(subCmd)) {
179         for (InputSection *isec : isd->sections) {
180           if (auto *ehSec = dyn_cast<EhFrameSection>(isec)) {
181             printEhFrame(os, ehSec);
182             continue;
183           }
184 
185           writeHeader(os, isec->getVA(), osec->getLMA() + isec->outSecOff,
186                       isec->getSize(), isec->alignment);
187           os << indent8 << toString(isec) << '\n';
188           for (Symbol *sym : llvm::make_first_range(sectionSyms[isec]))
189             os << symStr[sym] << '\n';
190         }
191         continue;
192       }
193 
194       if (auto *data = dyn_cast<ByteCommand>(subCmd)) {
195         writeHeader(os, osec->addr + data->offset,
196                     osec->getLMA() + data->offset, data->size, 1);
197         os << indent8 << data->commandString << '\n';
198         continue;
199       }
200 
201       if (auto *assign = dyn_cast<SymbolAssignment>(subCmd)) {
202         if (assign->provide && !assign->sym)
203           continue;
204         writeHeader(os, assign->addr,
205                     osec->getLMA() + assign->addr - osec->getVA(0),
206                     assign->size, 1);
207         os << indent8 << assign->commandString << '\n';
208         continue;
209       }
210     }
211   }
212 }
213 
214 void elf::writeWhyExtract() {
215   if (config->whyExtract.empty())
216     return;
217 
218   std::error_code ec;
219   raw_fd_ostream os(config->whyExtract, ec, sys::fs::OF_None);
220   if (ec) {
221     error("cannot open --why-extract= file " + config->whyExtract + ": " +
222           ec.message());
223     return;
224   }
225 
226   os << "reference\textracted\tsymbol\n";
227   for (auto &entry : whyExtract) {
228     os << std::get<0>(entry) << '\t' << toString(std::get<1>(entry)) << '\t'
229        << toString(std::get<2>(entry)) << '\n';
230   }
231 }
232 
233 // Output a cross reference table to stdout. This is for --cref.
234 //
235 // For each global symbol, we print out a file that defines the symbol
236 // followed by files that uses that symbol. Here is an example.
237 //
238 //     strlen     /lib/x86_64-linux-gnu/libc.so.6
239 //                tools/lld/tools/lld/CMakeFiles/lld.dir/lld.cpp.o
240 //                lib/libLLVMSupport.a(PrettyStackTrace.cpp.o)
241 //
242 // In this case, strlen is defined by libc.so.6 and used by other two
243 // files.
244 static void writeCref(raw_fd_ostream &os) {
245   // Collect symbols and files.
246   MapVector<Symbol *, SetVector<InputFile *>> map;
247   for (ELFFileBase *file : objectFiles) {
248     for (Symbol *sym : file->getSymbols()) {
249       if (isa<SharedSymbol>(sym))
250         map[sym].insert(file);
251       if (auto *d = dyn_cast<Defined>(sym))
252         if (!d->isLocal() && (!d->section || d->section->isLive()))
253           map[d].insert(file);
254     }
255   }
256 
257   auto print = [&](StringRef a, StringRef b) {
258     os << left_justify(a, 49) << ' ' << b << '\n';
259   };
260 
261   // Print a blank line and a header. The format matches GNU ld.
262   os << "\nCross Reference Table\n\n";
263   print("Symbol", "File");
264 
265   // Print out a table.
266   for (auto kv : map) {
267     Symbol *sym = kv.first;
268     SetVector<InputFile *> &files = kv.second;
269 
270     print(toString(*sym), toString(sym->file));
271     for (InputFile *file : files)
272       if (file != sym->file)
273         print("", toString(file));
274   }
275 }
276 
277 void elf::writeMapAndCref() {
278   if (config->mapFile.empty() && !config->cref)
279     return;
280 
281   llvm::TimeTraceScope timeScope("Write map file");
282 
283   // Open a map file for writing.
284   std::error_code ec;
285   StringRef mapFile = config->mapFile.empty() ? "-" : config->mapFile;
286   raw_fd_ostream os(mapFile, ec, sys::fs::OF_None);
287   if (ec) {
288     error("cannot open " + mapFile + ": " + ec.message());
289     return;
290   }
291 
292   if (!config->mapFile.empty())
293     writeMapFile(os);
294   if (config->cref)
295     writeCref(os);
296 }
297 
298 void elf::writeArchiveStats() {
299   if (config->printArchiveStats.empty())
300     return;
301 
302   std::error_code ec;
303   raw_fd_ostream os(config->printArchiveStats, ec, sys::fs::OF_None);
304   if (ec) {
305     error("--print-archive-stats=: cannot open " + config->printArchiveStats +
306           ": " + ec.message());
307     return;
308   }
309 
310   os << "members\textracted\tarchive\n";
311 
312   SmallVector<StringRef, 0> archives;
313   DenseMap<CachedHashStringRef, unsigned> all, extracted;
314   for (ELFFileBase *file : objectFiles)
315     if (file->archiveName.size())
316       ++extracted[CachedHashStringRef(file->archiveName)];
317   for (BitcodeFile *file : bitcodeFiles)
318     if (file->archiveName.size())
319       ++extracted[CachedHashStringRef(file->archiveName)];
320   for (std::pair<StringRef, unsigned> f : driver->archiveFiles) {
321     unsigned &v = extracted[CachedHashString(f.first)];
322     os << f.second << '\t' << v << '\t' << f.first << '\n';
323     // If the archive occurs multiple times, other instances have a count of 0.
324     v = 0;
325   }
326 }
327