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 "COFFLinkerContext.h"
23 #include "SymbolTable.h"
26 #include "lld/Common/ErrorHandler.h"
27 #include "llvm/Support/Parallel.h"
28 #include "llvm/Support/raw_ostream.h"
31 using namespace llvm::object
;
33 using namespace lld::coff
;
36 DenseMap
<const SectionChunk
*, SmallVector
<DefinedRegular
*, 4>>;
38 static constexpr char indent8
[] = " "; // 8 spaces
39 static constexpr char indent16
[] = " "; // 16 spaces
41 // Print out the first three columns of a line.
42 static void writeHeader(raw_ostream
&os
, uint64_t addr
, uint64_t size
,
44 os
<< format("%08llx %08llx %5lld ", addr
, size
, align
);
47 // Returns a list of all symbols that we want to print out.
48 static std::vector
<DefinedRegular
*> getSymbols(const COFFLinkerContext
&ctx
) {
49 std::vector
<DefinedRegular
*> v
;
50 for (ObjFile
*file
: ctx
.objFileInstances
)
51 for (Symbol
*b
: file
->getSymbols())
52 if (auto *sym
= dyn_cast_or_null
<DefinedRegular
>(b
))
53 if (sym
&& !sym
->getCOFFSymbol().isSectionDefinition())
58 // Returns a map from sections to their symbols.
59 static SymbolMapTy
getSectionSyms(ArrayRef
<DefinedRegular
*> syms
) {
61 for (DefinedRegular
*s
: syms
)
62 ret
[s
->getChunk()].push_back(s
);
64 // Sort symbols by address.
65 for (auto &it
: ret
) {
66 SmallVectorImpl
<DefinedRegular
*> &v
= it
.second
;
67 std::stable_sort(v
.begin(), v
.end(), [](DefinedRegular
*a
, DefinedRegular
*b
) {
68 return a
->getRVA() < b
->getRVA();
74 // Construct a map from symbols to their stringified representations.
75 static DenseMap
<DefinedRegular
*, std::string
>
76 getSymbolStrings(ArrayRef
<DefinedRegular
*> syms
) {
77 std::vector
<std::string
> str(syms
.size());
78 parallelForEachN((size_t)0, syms
.size(), [&](size_t i
) {
79 raw_string_ostream
os(str
[i
]);
80 writeHeader(os
, syms
[i
]->getRVA(), 0, 0);
81 os
<< indent16
<< toString(*syms
[i
]);
84 DenseMap
<DefinedRegular
*, std::string
> ret
;
85 for (size_t i
= 0, e
= syms
.size(); i
< e
; ++i
)
86 ret
[syms
[i
]] = std::move(str
[i
]);
90 void lld::coff::writeLLDMapFile(const COFFLinkerContext
&ctx
) {
91 if (config
->lldmapFile
.empty())
95 raw_fd_ostream
os(config
->lldmapFile
, ec
, sys::fs::OF_None
);
97 fatal("cannot open " + config
->lldmapFile
+ ": " + ec
.message());
99 // Collect symbol info that we want to print out.
100 std::vector
<DefinedRegular
*> syms
= getSymbols(ctx
);
101 SymbolMapTy sectionSyms
= getSectionSyms(syms
);
102 DenseMap
<DefinedRegular
*, std::string
> symStr
= getSymbolStrings(syms
);
104 // Print out the header line.
105 os
<< "Address Size Align Out In Symbol\n";
107 // Print out file contents.
108 for (OutputSection
*sec
: ctx
.outputSections
) {
109 writeHeader(os
, sec
->getRVA(), sec
->getVirtualSize(), /*align=*/pageSize
);
110 os
<< sec
->name
<< '\n';
112 for (Chunk
*c
: sec
->chunks
) {
113 auto *sc
= dyn_cast
<SectionChunk
>(c
);
117 writeHeader(os
, sc
->getRVA(), sc
->getSize(), sc
->getAlignment());
118 os
<< indent8
<< sc
->file
->getName() << ":(" << sc
->getSectionName()
120 for (DefinedRegular
*sym
: sectionSyms
[sc
])
121 os
<< symStr
[sym
] << '\n';