1 //===- MapFile.cpp --------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the -Map option. It shows lists in order and
10 // hierarchically the output sections, input sections, input files and
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)
19 //===----------------------------------------------------------------------===//
22 #include "InputFiles.h"
23 #include "LinkerScript.h"
24 #include "OutputSections.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/FileSystem.h"
31 #include "llvm/Support/Parallel.h"
32 #include "llvm/Support/TimeProfiler.h"
33 #include "llvm/Support/raw_ostream.h"
36 using namespace llvm::object
;
38 using namespace lld::elf
;
40 using SymbolMapTy
= DenseMap
<const SectionBase
*,
41 SmallVector
<std::pair
<Defined
*, uint64_t>, 0>>;
43 static constexpr char indent8
[] = " "; // 8 spaces
44 static constexpr char indent16
[] = " "; // 16 spaces
46 // Print out the first three columns of a line.
47 static void writeHeader(Ctx
&ctx
, raw_ostream
&os
, uint64_t vma
, uint64_t lma
,
48 uint64_t size
, uint64_t align
) {
50 os
<< format("%16llx %16llx %8llx %5lld ", vma
, lma
, size
, align
);
52 os
<< format("%8llx %8llx %8llx %5lld ", vma
, lma
, size
, align
);
55 // Returns a list of all symbols that we want to print out.
56 static std::vector
<Defined
*> getSymbols(Ctx
&ctx
) {
57 std::vector
<Defined
*> v
;
58 for (ELFFileBase
*file
: ctx
.objectFiles
)
59 for (Symbol
*b
: file
->getSymbols())
60 if (auto *dr
= dyn_cast
<Defined
>(b
))
61 if (!dr
->isSection() && dr
->section
&& dr
->section
->isLive() &&
62 (dr
->file
== file
|| dr
->hasFlag(NEEDS_COPY
) ||
63 (isa
<SyntheticSection
>(dr
->section
) &&
64 cast
<SyntheticSection
>(dr
->section
)->bss
)))
69 // Returns a map from sections to their symbols.
70 static SymbolMapTy
getSectionSyms(Ctx
&ctx
, ArrayRef
<Defined
*> syms
) {
72 for (Defined
*dr
: syms
)
73 ret
[dr
->section
].emplace_back(dr
, dr
->getVA(ctx
));
75 // Sort symbols by address. We want to print out symbols in the
76 // order in the output file rather than the order they appeared
77 // in the input files.
78 SmallPtrSet
<Defined
*, 4> set
;
79 for (auto &it
: ret
) {
80 // Deduplicate symbols which need a canonical PLT entry/copy relocation.
82 llvm::erase_if(it
.second
, [&](std::pair
<Defined
*, uint64_t> a
) {
83 return !set
.insert(a
.first
).second
;
86 llvm::stable_sort(it
.second
, llvm::less_second());
91 // Construct a map from symbols to their stringified representations.
92 // Demangling symbols (which is what toStr(ctx, ) does) is slow, so
93 // we do that in batch using parallel-for.
94 static DenseMap
<Symbol
*, std::string
>
95 getSymbolStrings(Ctx
&ctx
, ArrayRef
<Defined
*> syms
) {
96 auto strs
= std::make_unique
<std::string
[]>(syms
.size());
97 parallelFor(0, syms
.size(), [&](size_t i
) {
98 raw_string_ostream
os(strs
[i
]);
99 OutputSection
*osec
= syms
[i
]->getOutputSection();
100 uint64_t vma
= syms
[i
]->getVA(ctx
);
101 uint64_t lma
= osec
? osec
->getLMA() + vma
- osec
->getVA(0) : 0;
102 writeHeader(ctx
, os
, vma
, lma
, syms
[i
]->getSize(), 1);
103 os
<< indent16
<< toStr(ctx
, *syms
[i
]);
106 DenseMap
<Symbol
*, std::string
> ret
;
107 for (size_t i
= 0, e
= syms
.size(); i
< e
; ++i
)
108 ret
[syms
[i
]] = std::move(strs
[i
]);
112 // Print .eh_frame contents. Since the section consists of EhSectionPieces,
113 // we need a specialized printer for that section.
115 // .eh_frame tend to contain a lot of section pieces that are contiguous
116 // both in input file and output file. Such pieces are squashed before
117 // being displayed to make output compact.
118 static void printEhFrame(Ctx
&ctx
, raw_ostream
&os
, const EhFrameSection
*sec
) {
119 std::vector
<EhSectionPiece
> pieces
;
121 auto add
= [&](const EhSectionPiece
&p
) {
122 // If P is adjacent to Last, squash the two.
123 if (!pieces
.empty()) {
124 EhSectionPiece
&last
= pieces
.back();
125 if (last
.sec
== p
.sec
&& last
.inputOff
+ last
.size
== p
.inputOff
&&
126 last
.outputOff
+ last
.size
== (unsigned)p
.outputOff
) {
134 // Gather section pieces.
135 for (const CieRecord
*rec
: sec
->getCieRecords()) {
137 for (const EhSectionPiece
*fde
: rec
->fdes
)
141 // Print out section pieces.
142 const OutputSection
*osec
= sec
->getOutputSection();
143 for (EhSectionPiece
&p
: pieces
) {
144 writeHeader(ctx
, os
, osec
->addr
+ p
.outputOff
, osec
->getLMA() + p
.outputOff
,
146 os
<< indent8
<< toStr(ctx
, p
.sec
->file
) << ":(" << p
.sec
->name
<< "+0x"
147 << Twine::utohexstr(p
.inputOff
) + ")\n";
151 static void writeMapFile(Ctx
&ctx
, raw_fd_ostream
&os
) {
152 // Collect symbol info that we want to print out.
153 std::vector
<Defined
*> syms
= getSymbols(ctx
);
154 SymbolMapTy sectionSyms
= getSectionSyms(ctx
, syms
);
155 DenseMap
<Symbol
*, std::string
> symStr
= getSymbolStrings(ctx
, syms
);
157 // Print out the header line.
158 int w
= ctx
.arg
.is64
? 16 : 8;
159 os
<< right_justify("VMA", w
) << ' ' << right_justify("LMA", w
)
160 << " Size Align Out In Symbol\n";
162 OutputSection
*osec
= nullptr;
163 for (SectionCommand
*cmd
: ctx
.script
->sectionCommands
) {
164 if (auto *assign
= dyn_cast
<SymbolAssignment
>(cmd
)) {
165 if (assign
->provide
&& !assign
->sym
)
167 uint64_t lma
= osec
? osec
->getLMA() + assign
->addr
- osec
->getVA(0) : 0;
168 writeHeader(ctx
, os
, assign
->addr
, lma
, assign
->size
, 1);
169 os
<< assign
->commandString
<< '\n';
172 if (isa
<SectionClassDesc
>(cmd
))
175 osec
= &cast
<OutputDesc
>(cmd
)->osec
;
176 writeHeader(ctx
, os
, osec
->addr
, osec
->getLMA(), osec
->size
,
178 os
<< osec
->name
<< '\n';
180 // Dump symbols for each input section.
181 for (SectionCommand
*subCmd
: osec
->commands
) {
182 if (auto *isd
= dyn_cast
<InputSectionDescription
>(subCmd
)) {
183 for (InputSection
*isec
: isd
->sections
) {
184 if (auto *ehSec
= dyn_cast
<EhFrameSection
>(isec
)) {
185 printEhFrame(ctx
, os
, ehSec
);
189 writeHeader(ctx
, os
, isec
->getVA(), osec
->getLMA() + isec
->outSecOff
,
190 isec
->getSize(), isec
->addralign
);
191 os
<< indent8
<< toStr(ctx
, isec
) << '\n';
192 for (Symbol
*sym
: llvm::make_first_range(sectionSyms
[isec
]))
193 os
<< symStr
[sym
] << '\n';
198 if (auto *data
= dyn_cast
<ByteCommand
>(subCmd
)) {
199 writeHeader(ctx
, os
, osec
->addr
+ data
->offset
,
200 osec
->getLMA() + data
->offset
, data
->size
, 1);
201 os
<< indent8
<< data
->commandString
<< '\n';
205 if (auto *assign
= dyn_cast
<SymbolAssignment
>(subCmd
)) {
206 if (assign
->provide
&& !assign
->sym
)
208 writeHeader(ctx
, os
, assign
->addr
,
209 osec
->getLMA() + assign
->addr
- osec
->getVA(0),
211 os
<< indent8
<< assign
->commandString
<< '\n';
218 // Output a cross reference table to stdout. This is for --cref.
220 // For each global symbol, we print out a file that defines the symbol
221 // followed by files that uses that symbol. Here is an example.
223 // strlen /lib/x86_64-linux-gnu/libc.so.6
224 // tools/lld/tools/lld/CMakeFiles/lld.dir/lld.cpp.o
225 // lib/libLLVMSupport.a(PrettyStackTrace.cpp.o)
227 // In this case, strlen is defined by libc.so.6 and used by other two
229 static void writeCref(Ctx
&ctx
, raw_fd_ostream
&os
) {
230 // Collect symbols and files.
231 MapVector
<Symbol
*, SetVector
<InputFile
*>> map
;
232 for (ELFFileBase
*file
: ctx
.objectFiles
) {
233 for (Symbol
*sym
: file
->getSymbols()) {
234 if (isa
<SharedSymbol
>(sym
))
235 map
[sym
].insert(file
);
236 if (auto *d
= dyn_cast
<Defined
>(sym
))
242 auto print
= [&](StringRef a
, StringRef b
) {
243 os
<< left_justify(a
, 49) << ' ' << b
<< '\n';
246 // Print a blank line and a header. The format matches GNU ld.
247 os
<< "\nCross Reference Table\n\n";
248 print("Symbol", "File");
250 // Print out a table.
251 for (auto kv
: map
) {
252 Symbol
*sym
= kv
.first
;
253 SetVector
<InputFile
*> &files
= kv
.second
;
255 print(toStr(ctx
, *sym
), toStr(ctx
, sym
->file
));
256 for (InputFile
*file
: files
)
257 if (file
!= sym
->file
)
258 print("", toStr(ctx
, file
));
262 void elf::writeMapAndCref(Ctx
&ctx
) {
263 if (ctx
.arg
.mapFile
.empty() && !ctx
.arg
.cref
)
266 llvm::TimeTraceScope
timeScope("Write map file");
268 // Open a map file for writing.
270 StringRef mapFile
= ctx
.arg
.mapFile
.empty() ? "-" : ctx
.arg
.mapFile
;
271 raw_fd_ostream os
= ctx
.openAuxiliaryFile(mapFile
, ec
);
273 ErrAlways(ctx
) << "cannot open " << mapFile
<< ": " << ec
.message();
277 if (!ctx
.arg
.mapFile
.empty())
278 writeMapFile(ctx
, os
);