1 //===- MapFile.cpp --------------------------------------------------------===//
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the /lldmap option. It shows lists in order and
11 // hierarchically the output sections, input sections, input files and
14 // Address Size Align Out File Symbol
15 // 00201000 00000015 4 .text
16 // 00201000 0000000e 4 test.o:(.text)
17 // 0020100e 00000000 0 local
18 // 00201005 00000000 0 f(int)
20 //===----------------------------------------------------------------------===//
24 #include "SymbolTable.h"
28 #include "llvm/Support/Parallel.h"
29 #include "llvm/Support/raw_ostream.h"
32 using namespace llvm::object
;
35 using namespace lld::coff
;
37 typedef DenseMap
<const SectionChunk
*, SmallVector
<DefinedRegular
*, 4>>
40 // Print out the first three columns of a line.
41 static void writeHeader(raw_ostream
&OS
, uint64_t Addr
, uint64_t Size
,
43 OS
<< format("%08llx %08llx %5lld ", Addr
, Size
, Align
);
46 static std::string
indent(int Depth
) { return std::string(Depth
* 8, ' '); }
48 // Returns a list of all symbols that we want to print out.
49 static std::vector
<DefinedRegular
*> getSymbols() {
50 std::vector
<DefinedRegular
*> V
;
51 for (ObjFile
*File
: ObjFile::Instances
)
52 for (SymbolBody
*B
: File
->getSymbols())
53 if (auto *Sym
= dyn_cast
<DefinedRegular
>(B
))
54 if (Sym
&& !Sym
->getCOFFSymbol().isSectionDefinition())
59 // Returns a map from sections to their symbols.
60 static SymbolMapTy
getSectionSyms(ArrayRef
<DefinedRegular
*> Syms
) {
62 for (DefinedRegular
*S
: Syms
)
63 Ret
[S
->getChunk()].push_back(S
);
65 // Sort symbols by address.
66 for (auto &It
: Ret
) {
67 SmallVectorImpl
<DefinedRegular
*> &V
= It
.second
;
68 std::sort(V
.begin(), V
.end(), [](DefinedRegular
*A
, DefinedRegular
*B
) {
69 return A
->getRVA() < B
->getRVA();
75 // Construct a map from symbols to their stringified representations.
76 static DenseMap
<DefinedRegular
*, std::string
>
77 getSymbolStrings(ArrayRef
<DefinedRegular
*> Syms
) {
78 std::vector
<std::string
> Str(Syms
.size());
79 for_each_n(parallel::par
, (size_t)0, Syms
.size(), [&](size_t I
) {
80 raw_string_ostream
OS(Str
[I
]);
81 writeHeader(OS
, Syms
[I
]->getRVA(), 0, 0);
82 OS
<< indent(2) << toString(*Syms
[I
]);
85 DenseMap
<DefinedRegular
*, std::string
> Ret
;
86 for (size_t I
= 0, E
= Syms
.size(); I
< E
; ++I
)
87 Ret
[Syms
[I
]] = std::move(Str
[I
]);
91 void coff::writeMapFile(ArrayRef
<OutputSection
*> OutputSections
) {
92 if (Config
->MapFile
.empty())
96 raw_fd_ostream
OS(Config
->MapFile
, EC
, sys::fs::F_None
);
98 fatal("cannot open " + Config
->MapFile
+ ": " + EC
.message());
100 // Collect symbol info that we want to print out.
101 std::vector
<DefinedRegular
*> Syms
= getSymbols();
102 SymbolMapTy SectionSyms
= getSectionSyms(Syms
);
103 DenseMap
<DefinedRegular
*, std::string
> SymStr
= getSymbolStrings(Syms
);
105 // Print out the header line.
106 OS
<< "Address Size Align Out In Symbol\n";
108 // Print out file contents.
109 for (OutputSection
*Sec
: OutputSections
) {
110 writeHeader(OS
, Sec
->getRVA(), Sec
->getVirtualSize(), /*Align=*/PageSize
);
111 OS
<< Sec
->getName() << '\n';
113 for (Chunk
*C
: Sec
->getChunks()) {
114 auto *SC
= dyn_cast
<SectionChunk
>(C
);
118 writeHeader(OS
, SC
->getRVA(), SC
->getSize(), SC
->getAlign());
119 OS
<< indent(1) << SC
->File
->getName() << ":(" << SC
->getSectionName()
121 for (DefinedRegular
*Sym
: SectionSyms
[SC
])
122 OS
<< SymStr
[Sym
] << '\n';