1 //===- LLDMapFile.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 /lldmap option. It shows lists in order and
10 // hierarchically the output sections, input sections, input files and
13 // Address Size Align Out File 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 //===----------------------------------------------------------------------===//
21 #include "LLDMapFile.h"
22 #include "SymbolTable.h"
25 #include "lld/Common/ErrorHandler.h"
26 #include "llvm/Support/Parallel.h"
27 #include "llvm/Support/raw_ostream.h"
30 using namespace llvm::object
;
32 using namespace lld::coff
;
35 DenseMap
<const SectionChunk
*, SmallVector
<DefinedRegular
*, 4>>;
37 static constexpr char indent8
[] = " "; // 8 spaces
38 static constexpr char indent16
[] = " "; // 16 spaces
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 // Returns a list of all symbols that we want to print out.
47 static std::vector
<DefinedRegular
*> getSymbols() {
48 std::vector
<DefinedRegular
*> v
;
49 for (ObjFile
*file
: ObjFile::instances
)
50 for (Symbol
*b
: file
->getSymbols())
51 if (auto *sym
= dyn_cast_or_null
<DefinedRegular
>(b
))
52 if (sym
&& !sym
->getCOFFSymbol().isSectionDefinition())
57 // Returns a map from sections to their symbols.
58 static SymbolMapTy
getSectionSyms(ArrayRef
<DefinedRegular
*> syms
) {
60 for (DefinedRegular
*s
: syms
)
61 ret
[s
->getChunk()].push_back(s
);
63 // Sort symbols by address.
64 for (auto &it
: ret
) {
65 SmallVectorImpl
<DefinedRegular
*> &v
= it
.second
;
66 std::stable_sort(v
.begin(), v
.end(), [](DefinedRegular
*a
, DefinedRegular
*b
) {
67 return a
->getRVA() < b
->getRVA();
73 // Construct a map from symbols to their stringified representations.
74 static DenseMap
<DefinedRegular
*, std::string
>
75 getSymbolStrings(ArrayRef
<DefinedRegular
*> syms
) {
76 std::vector
<std::string
> str(syms
.size());
77 parallelForEachN((size_t)0, syms
.size(), [&](size_t i
) {
78 raw_string_ostream
os(str
[i
]);
79 writeHeader(os
, syms
[i
]->getRVA(), 0, 0);
80 os
<< indent16
<< toString(*syms
[i
]);
83 DenseMap
<DefinedRegular
*, std::string
> ret
;
84 for (size_t i
= 0, e
= syms
.size(); i
< e
; ++i
)
85 ret
[syms
[i
]] = std::move(str
[i
]);
89 void lld::coff::writeLLDMapFile(ArrayRef
<OutputSection
*> outputSections
) {
90 if (config
->lldmapFile
.empty())
94 raw_fd_ostream
os(config
->lldmapFile
, ec
, sys::fs::OF_None
);
96 fatal("cannot open " + config
->lldmapFile
+ ": " + ec
.message());
98 // Collect symbol info that we want to print out.
99 std::vector
<DefinedRegular
*> syms
= getSymbols();
100 SymbolMapTy sectionSyms
= getSectionSyms(syms
);
101 DenseMap
<DefinedRegular
*, std::string
> symStr
= getSymbolStrings(syms
);
103 // Print out the header line.
104 os
<< "Address Size Align Out In Symbol\n";
106 // Print out file contents.
107 for (OutputSection
*sec
: outputSections
) {
108 writeHeader(os
, sec
->getRVA(), sec
->getVirtualSize(), /*align=*/pageSize
);
109 os
<< sec
->name
<< '\n';
111 for (Chunk
*c
: sec
->chunks
) {
112 auto *sc
= dyn_cast
<SectionChunk
>(c
);
116 writeHeader(os
, sc
->getRVA(), sc
->getSize(), sc
->getAlignment());
117 os
<< indent8
<< sc
->file
->getName() << ":(" << sc
->getSectionName()
119 for (DefinedRegular
*sym
: sectionSyms
[sc
])
120 os
<< symStr
[sym
] << '\n';