Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[lld-link] Support /map option, matching link.exe 's /map output format
Added support for /map and /map:[filepath]. The output was derived from Microsoft's Link.exe output when using that same option. Note that /MAPINFO support was not added. The previous implementation of MapFile.cpp/.h was meant for /lldmap, and was renamed to LLDMapFile.cpp/.h MapFile.cpp/.h is now for /MAP However, a small fix was added to lldmap, replacing a std::sort with std::stable_sort to enforce reproducibility. Differential Revision: https://reviews.llvm.org/D70557
- Loading branch information
1 parent
177dd63
commit b91905a
Showing
11 changed files
with
521 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
//===- LLDMapFile.cpp -----------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file implements the /lldmap option. It shows lists in order and | ||
// hierarchically the output sections, input sections, input files and | ||
// symbol: | ||
// | ||
// Address Size Align Out File Symbol | ||
// 00201000 00000015 4 .text | ||
// 00201000 0000000e 4 test.o:(.text) | ||
// 0020100e 00000000 0 local | ||
// 00201005 00000000 0 f(int) | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "LLDMapFile.h" | ||
#include "SymbolTable.h" | ||
#include "Symbols.h" | ||
#include "Writer.h" | ||
#include "lld/Common/ErrorHandler.h" | ||
#include "lld/Common/Threads.h" | ||
#include "llvm/Support/raw_ostream.h" | ||
|
||
using namespace llvm; | ||
using namespace llvm::object; | ||
using namespace lld; | ||
using namespace lld::coff; | ||
|
||
using SymbolMapTy = | ||
DenseMap<const SectionChunk *, SmallVector<DefinedRegular *, 4>>; | ||
|
||
static constexpr char indent8[] = " "; // 8 spaces | ||
static constexpr char indent16[] = " "; // 16 spaces | ||
|
||
// Print out the first three columns of a line. | ||
static void writeHeader(raw_ostream &os, uint64_t addr, uint64_t size, | ||
uint64_t align) { | ||
os << format("%08llx %08llx %5lld ", addr, size, align); | ||
} | ||
|
||
// Returns a list of all symbols that we want to print out. | ||
static std::vector<DefinedRegular *> getSymbols() { | ||
std::vector<DefinedRegular *> v; | ||
for (ObjFile *file : ObjFile::instances) | ||
for (Symbol *b : file->getSymbols()) | ||
if (auto *sym = dyn_cast_or_null<DefinedRegular>(b)) | ||
if (sym && !sym->getCOFFSymbol().isSectionDefinition()) | ||
v.push_back(sym); | ||
return v; | ||
} | ||
|
||
// Returns a map from sections to their symbols. | ||
static SymbolMapTy getSectionSyms(ArrayRef<DefinedRegular *> syms) { | ||
SymbolMapTy ret; | ||
for (DefinedRegular *s : syms) | ||
ret[s->getChunk()].push_back(s); | ||
|
||
// Sort symbols by address. | ||
for (auto &it : ret) { | ||
SmallVectorImpl<DefinedRegular *> &v = it.second; | ||
std::stable_sort(v.begin(), v.end(), [](DefinedRegular *a, DefinedRegular *b) { | ||
return a->getRVA() < b->getRVA(); | ||
}); | ||
} | ||
return ret; | ||
} | ||
|
||
// Construct a map from symbols to their stringified representations. | ||
static DenseMap<DefinedRegular *, std::string> | ||
getSymbolStrings(ArrayRef<DefinedRegular *> syms) { | ||
std::vector<std::string> str(syms.size()); | ||
parallelForEachN((size_t)0, syms.size(), [&](size_t i) { | ||
raw_string_ostream os(str[i]); | ||
writeHeader(os, syms[i]->getRVA(), 0, 0); | ||
os << indent16 << toString(*syms[i]); | ||
}); | ||
|
||
DenseMap<DefinedRegular *, std::string> ret; | ||
for (size_t i = 0, e = syms.size(); i < e; ++i) | ||
ret[syms[i]] = std::move(str[i]); | ||
return ret; | ||
} | ||
|
||
void lld::coff::writeLLDMapFile(ArrayRef<OutputSection *> outputSections) { | ||
if (config->lldmapFile.empty()) | ||
return; | ||
|
||
std::error_code ec; | ||
raw_fd_ostream os(config->lldmapFile, ec, sys::fs::OF_None); | ||
if (ec) | ||
fatal("cannot open " + config->lldmapFile + ": " + ec.message()); | ||
|
||
// Collect symbol info that we want to print out. | ||
std::vector<DefinedRegular *> syms = getSymbols(); | ||
SymbolMapTy sectionSyms = getSectionSyms(syms); | ||
DenseMap<DefinedRegular *, std::string> symStr = getSymbolStrings(syms); | ||
|
||
// Print out the header line. | ||
os << "Address Size Align Out In Symbol\n"; | ||
|
||
// Print out file contents. | ||
for (OutputSection *sec : outputSections) { | ||
writeHeader(os, sec->getRVA(), sec->getVirtualSize(), /*align=*/pageSize); | ||
os << sec->name << '\n'; | ||
|
||
for (Chunk *c : sec->chunks) { | ||
auto *sc = dyn_cast<SectionChunk>(c); | ||
if (!sc) | ||
continue; | ||
|
||
writeHeader(os, sc->getRVA(), sc->getSize(), sc->getAlignment()); | ||
os << indent8 << sc->file->getName() << ":(" << sc->getSectionName() | ||
<< ")\n"; | ||
for (DefinedRegular *sym : sectionSyms[sc]) | ||
os << symStr[sym] << '\n'; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
//===- LLDMapFile.h ---------------------------------------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLD_COFF_LLDMAPFILE_H | ||
#define LLD_COFF_LLDMAPFILE_H | ||
|
||
#include "llvm/ADT/ArrayRef.h" | ||
|
||
namespace lld { | ||
namespace coff { | ||
class OutputSection; | ||
void writeLLDMapFile(llvm::ArrayRef<OutputSection *> outputSections); | ||
} | ||
} | ||
|
||
#endif |
Oops, something went wrong.