[lld] r291990 - COFF: Change the /lldmap output format to be more like the ELF linker.
Peter Collingbourne via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 13 19:14:46 PST 2017
Author: pcc
Date: Fri Jan 13 21:14:46 2017
New Revision: 291990
URL: http://llvm.org/viewvc/llvm-project?rev=291990&view=rev
Log:
COFF: Change the /lldmap output format to be more like the ELF linker.
Differential Revision: https://reviews.llvm.org/D28717
Added:
lld/trunk/COFF/MapFile.cpp
lld/trunk/COFF/MapFile.h
Modified:
lld/trunk/COFF/CMakeLists.txt
lld/trunk/COFF/Chunks.h
lld/trunk/COFF/Config.h
lld/trunk/COFF/Driver.cpp
lld/trunk/COFF/SymbolTable.cpp
lld/trunk/COFF/SymbolTable.h
lld/trunk/COFF/Writer.cpp
lld/trunk/COFF/Writer.h
lld/trunk/test/COFF/lldmap.test
lld/trunk/test/COFF/lto-parallel.ll
lld/trunk/test/COFF/weak-external.test
lld/trunk/test/COFF/weak-external3.test
Modified: lld/trunk/COFF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/CMakeLists.txt?rev=291990&r1=291989&r2=291990&view=diff
==============================================================================
--- lld/trunk/COFF/CMakeLists.txt (original)
+++ lld/trunk/COFF/CMakeLists.txt Fri Jan 13 21:14:46 2017
@@ -15,6 +15,7 @@ add_lld_library(lldCOFF
ICF.cpp
InputFiles.cpp
Librarian.cpp
+ MapFile.cpp
MarkLive.cpp
ModuleDef.cpp
PDB.cpp
Modified: lld/trunk/COFF/Chunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.h?rev=291990&r1=291989&r2=291990&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.h (original)
+++ lld/trunk/COFF/Chunks.h Fri Jan 13 21:14:46 2017
@@ -187,10 +187,10 @@ public:
const coff_section *Header;
-private:
- // A file this chunk was created from.
+ // The file that this chunk was created from.
ObjectFile *File;
+private:
StringRef SectionName;
std::vector<SectionChunk *> AssocChildren;
llvm::iterator_range<const coff_relocation *> Relocs;
Modified: lld/trunk/COFF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Config.h?rev=291990&r1=291989&r2=291990&view=diff
==============================================================================
--- lld/trunk/COFF/Config.h (original)
+++ lld/trunk/COFF/Config.h Fri Jan 13 21:14:46 2017
@@ -135,6 +135,9 @@ struct Configuration {
// Used for /alternatename.
std::map<StringRef, StringRef> AlternateNames;
+ // Used for /lldmap.
+ std::string MapFile;
+
uint64_t ImageBase = -1;
uint64_t StackReserve = 1024 * 1024;
uint64_t StackCommit = 4096;
Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=291990&r1=291989&r2=291990&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Fri Jan 13 21:14:46 2017
@@ -658,6 +658,8 @@ void LinkerDriver::link(ArrayRef<const c
Config->DumpPdb = Args.hasArg(OPT_dumppdb);
Config->DebugPdb = Args.hasArg(OPT_debugpdb);
+ Config->MapFile = getMapFile(Args);
+
// Create a list of input files. Files can be given as arguments
// for /defaultlib option.
std::vector<MemoryBufferRef> MBs;
@@ -846,17 +848,6 @@ void LinkerDriver::link(ArrayRef<const c
// Write the result.
writeResult(&Symtab);
- // Create a symbol map file containing symbol VAs and their names
- // to help debugging.
- std::string MapFile = getMapFile(Args);
- if (!MapFile.empty()) {
- std::error_code EC;
- raw_fd_ostream Out(MapFile, EC, OpenFlags::F_Text);
- if (EC)
- fatal(EC, "could not create the symbol map " + MapFile);
- Symtab.printMap(Out);
- }
-
// Call exit to avoid calling destructors.
exit(0);
}
Added: lld/trunk/COFF/MapFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/MapFile.cpp?rev=291990&view=auto
==============================================================================
--- lld/trunk/COFF/MapFile.cpp (added)
+++ lld/trunk/COFF/MapFile.cpp Fri Jan 13 21:14:46 2017
@@ -0,0 +1,125 @@
+//===- MapFile.cpp --------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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 In File Symbol
+// =================================================================
+// 00201000 00000015 4 .text
+// 00201000 0000000e 4 .text
+// 00201000 0000000e 4 test.o
+// 0020100e 00000000 0 local
+// 00201005 00000000 0 f(int)
+//
+//===----------------------------------------------------------------------===//
+
+#include "MapFile.h"
+#include "Error.h"
+#include "Symbols.h"
+#include "Writer.h"
+
+#include "llvm/Support/FileUtilities.h"
+
+using namespace llvm;
+using namespace llvm::object;
+
+using namespace lld;
+using namespace lld::coff;
+
+static void writeOutSecLine(raw_fd_ostream &OS, uint64_t Address, uint64_t Size,
+ uint64_t Align, StringRef Name) {
+ OS << format_hex_no_prefix(Address, 8) << ' '
+ << format_hex_no_prefix(Size, 8) << ' ' << format("%5x ", Align)
+ << left_justify(Name, 7);
+}
+
+static void writeInSecLine(raw_fd_ostream &OS, uint64_t Address, uint64_t Size,
+ uint64_t Align, StringRef Name) {
+ // Pass an empty name to align the text to the correct column.
+ writeOutSecLine(OS, Address, Size, Align, "");
+ OS << ' ' << left_justify(Name, 7);
+}
+
+static void writeFileLine(raw_fd_ostream &OS, uint64_t Address, uint64_t Size,
+ uint64_t Align, StringRef Name) {
+ // Pass an empty name to align the text to the correct column.
+ writeInSecLine(OS, Address, Size, Align, "");
+ OS << ' ' << left_justify(Name, 7);
+}
+
+static void writeSymbolLine(raw_fd_ostream &OS, uint64_t Address, uint64_t Size,
+ StringRef Name) {
+ // Pass an empty name to align the text to the correct column.
+ writeFileLine(OS, Address, Size, 0, "");
+ OS << ' ' << left_justify(Name, 7);
+}
+
+static void writeSectionChunk(raw_fd_ostream &OS, const SectionChunk *SC,
+ StringRef &PrevName) {
+ StringRef Name = SC->getSectionName();
+ if (Name != PrevName) {
+ writeInSecLine(OS, SC->getRVA(), SC->getSize(), SC->getAlign(), Name);
+ OS << '\n';
+ PrevName = Name;
+ }
+ coff::ObjectFile *File = SC->File;
+ if (!File)
+ return;
+ writeFileLine(OS, SC->getRVA(), SC->getSize(), SC->getAlign(),
+ toString(File));
+ OS << '\n';
+ ArrayRef<SymbolBody *> Syms = File->getSymbols();
+ for (SymbolBody *Sym : Syms) {
+ auto *DR = dyn_cast<DefinedRegular>(Sym);
+ if (!DR || DR->getChunk() != SC ||
+ DR->getCOFFSymbol().isSectionDefinition())
+ continue;
+ writeSymbolLine(OS, DR->getRVA(), SC->getSize(), toString(*Sym));
+ OS << '\n';
+ }
+}
+
+static void writeMapFile2(int FD,
+ ArrayRef<OutputSection *> OutputSections) {
+ raw_fd_ostream OS(FD, true);
+ OS << left_justify("Address", 8) << ' ' << left_justify("Size", 8)
+ << ' ' << left_justify("Align", 5) << ' ' << left_justify("Out", 7) << ' '
+ << left_justify("In", 7) << ' ' << left_justify("File", 7) << " Symbol\n";
+ for (OutputSection *Sec : OutputSections) {
+ uint32_t VA = Sec->getRVA();
+ writeOutSecLine(OS, VA, Sec->getVirtualSize(), /*Align=*/PageSize,
+ Sec->getName());
+ OS << '\n';
+ StringRef PrevName = "";
+ for (Chunk *C : Sec->getChunks())
+ if (const auto *SC = dyn_cast<SectionChunk>(C))
+ writeSectionChunk(OS, SC, PrevName);
+ }
+}
+
+void coff::writeMapFile(ArrayRef<OutputSection *> OutputSections) {
+ StringRef MapFile = Config->MapFile;
+ if (MapFile.empty())
+ return;
+
+ // Create new file in same directory but with random name.
+ SmallString<128> TempPath;
+ int FD;
+ std::error_code EC =
+ sys::fs::createUniqueFile(Twine(MapFile) + ".tmp%%%%%%%", FD, TempPath);
+ if (EC)
+ fatal(EC.message());
+ FileRemover RAII(TempPath);
+ writeMapFile2(FD, OutputSections);
+ EC = sys::fs::rename(TempPath, MapFile);
+ if (EC)
+ fatal(EC.message());
+}
Added: lld/trunk/COFF/MapFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/MapFile.h?rev=291990&view=auto
==============================================================================
--- lld/trunk/COFF/MapFile.h (added)
+++ lld/trunk/COFF/MapFile.h Fri Jan 13 21:14:46 2017
@@ -0,0 +1,22 @@
+//===- MapFile.h ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_COFF_MAPFILE_H
+#define LLD_COFF_MAPFILE_H
+
+#include "llvm/ADT/ArrayRef.h"
+
+namespace lld {
+namespace coff {
+class OutputSection;
+void writeMapFile(llvm::ArrayRef<OutputSection *> OutputSections);
+}
+}
+
+#endif
Modified: lld/trunk/COFF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/SymbolTable.cpp?rev=291990&r1=291989&r2=291990&view=diff
==============================================================================
--- lld/trunk/COFF/SymbolTable.cpp (original)
+++ lld/trunk/COFF/SymbolTable.cpp Fri Jan 13 21:14:46 2017
@@ -345,17 +345,6 @@ SymbolBody *SymbolTable::addUndefined(St
return addUndefined(Name, nullptr, false)->body();
}
-void SymbolTable::printMap(llvm::raw_ostream &OS) {
- for (ObjectFile *File : ObjectFiles) {
- OS << toString(File) << ":\n";
- for (SymbolBody *Body : File->getSymbols())
- if (auto *R = dyn_cast<DefinedRegular>(Body))
- if (R->getChunk()->isLive())
- OS << Twine::utohexstr(Config->ImageBase + R->getRVA())
- << " " << R->getName() << "\n";
- }
-}
-
void SymbolTable::addCombinedLTOObjects() {
if (BitcodeFiles.empty())
return;
Modified: lld/trunk/COFF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/SymbolTable.h?rev=291990&r1=291989&r2=291990&view=diff
==============================================================================
--- lld/trunk/COFF/SymbolTable.h (original)
+++ lld/trunk/COFF/SymbolTable.h Fri Jan 13 21:14:46 2017
@@ -69,9 +69,6 @@ public:
void mangleMaybe(SymbolBody *B);
StringRef findMangle(StringRef Name);
- // Print a layout map to OS.
- void printMap(llvm::raw_ostream &OS);
-
// Build a set of COFF objects representing the combined contents of
// BitcodeFiles and add them to the symbol table. Called after all files are
// added and before the writer writes results to a file.
Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=291990&r1=291989&r2=291990&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Fri Jan 13 21:14:46 2017
@@ -12,6 +12,7 @@
#include "DLL.h"
#include "Error.h"
#include "InputFiles.h"
+#include "MapFile.h"
#include "Memory.h"
#include "PDB.h"
#include "SymbolTable.h"
@@ -39,7 +40,6 @@ using namespace llvm::support::endian;
using namespace lld;
using namespace lld::coff;
-static const int PageSize = 4096;
static const int SectorSize = 512;
static const int DOSStubSize = 64;
static const int NumberfOfDataDirectory = 16;
@@ -163,51 +163,6 @@ namespace coff {
void writeResult(SymbolTable *T) { Writer(T).run(); }
-// OutputSection represents a section in an output file. It's a
-// container of chunks. OutputSection and Chunk are 1:N relationship.
-// Chunks cannot belong to more than one OutputSections. The writer
-// creates multiple OutputSections and assign them unique,
-// non-overlapping file offsets and RVAs.
-class OutputSection {
-public:
- OutputSection(StringRef N) : Name(N), Header({}) {}
- void setRVA(uint64_t);
- void setFileOffset(uint64_t);
- void addChunk(Chunk *C);
- StringRef getName() { return Name; }
- std::vector<Chunk *> &getChunks() { return Chunks; }
- void addPermissions(uint32_t C);
- void setPermissions(uint32_t C);
- uint32_t getPermissions() { return Header.Characteristics & PermMask; }
- uint32_t getCharacteristics() { return Header.Characteristics; }
- uint64_t getRVA() { return Header.VirtualAddress; }
- uint64_t getFileOff() { return Header.PointerToRawData; }
- void writeHeaderTo(uint8_t *Buf);
-
- // Returns the size of this section in an executable memory image.
- // This may be smaller than the raw size (the raw size is multiple
- // of disk sector size, so there may be padding at end), or may be
- // larger (if that's the case, the loader reserves spaces after end
- // of raw data).
- uint64_t getVirtualSize() { return Header.VirtualSize; }
-
- // Returns the size of the section in the output file.
- uint64_t getRawSize() { return Header.SizeOfRawData; }
-
- // Set offset into the string table storing this section name.
- // Used only when the name is longer than 8 bytes.
- void setStringTableOff(uint32_t V) { StringTableOff = V; }
-
- // N.B. The section index is one based.
- uint32_t SectionIndex = 0;
-
-private:
- StringRef Name;
- coff_section Header;
- uint32_t StringTableOff = 0;
- std::vector<Chunk *> Chunks;
-};
-
void OutputSection::setRVA(uint64_t RVA) {
Header.VirtualAddress = RVA;
for (Chunk *C : Chunks)
@@ -306,6 +261,8 @@ void Writer::run() {
if (!Config->PDBPath.empty())
createPDB(Config->PDBPath, Symtab, SectionTable, BuildId->DI);
+ writeMapFile(OutputSections);
+
if (auto EC = Buffer->commit())
fatal(EC, "failed to write the output file");
}
Modified: lld/trunk/COFF/Writer.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.h?rev=291990&r1=291989&r2=291990&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.h (original)
+++ lld/trunk/COFF/Writer.h Fri Jan 13 21:14:46 2017
@@ -10,14 +10,65 @@
#ifndef LLD_COFF_WRITER_H
#define LLD_COFF_WRITER_H
+#include "Chunks.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Object/COFF.h"
+#include <cstdint>
#include <vector>
namespace lld {
namespace coff {
class SymbolTable;
+static const int PageSize = 4096;
+
void writeResult(SymbolTable *T);
+// OutputSection represents a section in an output file. It's a
+// container of chunks. OutputSection and Chunk are 1:N relationship.
+// Chunks cannot belong to more than one OutputSections. The writer
+// creates multiple OutputSections and assign them unique,
+// non-overlapping file offsets and RVAs.
+class OutputSection {
+public:
+ OutputSection(llvm::StringRef N) : Name(N), Header({}) {}
+ void setRVA(uint64_t);
+ void setFileOffset(uint64_t);
+ void addChunk(Chunk *C);
+ llvm::StringRef getName() { return Name; }
+ std::vector<Chunk *> &getChunks() { return Chunks; }
+ void addPermissions(uint32_t C);
+ void setPermissions(uint32_t C);
+ uint32_t getPermissions() { return Header.Characteristics & PermMask; }
+ uint32_t getCharacteristics() { return Header.Characteristics; }
+ uint64_t getRVA() { return Header.VirtualAddress; }
+ uint64_t getFileOff() { return Header.PointerToRawData; }
+ void writeHeaderTo(uint8_t *Buf);
+
+ // Returns the size of this section in an executable memory image.
+ // This may be smaller than the raw size (the raw size is multiple
+ // of disk sector size, so there may be padding at end), or may be
+ // larger (if that's the case, the loader reserves spaces after end
+ // of raw data).
+ uint64_t getVirtualSize() { return Header.VirtualSize; }
+
+ // Returns the size of the section in the output file.
+ uint64_t getRawSize() { return Header.SizeOfRawData; }
+
+ // Set offset into the string table storing this section name.
+ // Used only when the name is longer than 8 bytes.
+ void setStringTableOff(uint32_t V) { StringTableOff = V; }
+
+ // N.B. The section index is one based.
+ uint32_t SectionIndex = 0;
+
+private:
+ llvm::StringRef Name;
+ llvm::object::coff_section Header;
+ uint32_t StringTableOff = 0;
+ std::vector<Chunk *> Chunks;
+};
+
}
}
Modified: lld/trunk/test/COFF/lldmap.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/lldmap.test?rev=291990&r1=291989&r2=291990&view=diff
==============================================================================
--- lld/trunk/test/COFF/lldmap.test (original)
+++ lld/trunk/test/COFF/lldmap.test Fri Jan 13 21:14:46 2017
@@ -4,7 +4,8 @@
# RUN: lld-link /out:%T/bar.exe /entry:main /lldmap %t.obj
# RUN: FileCheck %s < %T/bar.map
-# CHECK: .obj:
-# CHECK-NEXT: 140001000 .text$mn
-# CHECK-NEXT: 140001000 .data
-# CHECK-NEXT: 140001000 main
+# CHECK: Address Size Align Out In File Symbol
+# CHECK-NEXT: 00001000 00000006 1000 .text
+# CHECK-NEXT: 00001000 00000006 10 .text$mn
+# CHECK-NEXT: 00001000 00000006 10 {{.*}}lldmap.test.tmp.obj
+# CHECK-NEXT: 00001000 00000006 0 main
Modified: lld/trunk/test/COFF/lto-parallel.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/lto-parallel.ll?rev=291990&r1=291989&r2=291990&view=diff
==============================================================================
--- lld/trunk/test/COFF/lto-parallel.ll (original)
+++ lld/trunk/test/COFF/lto-parallel.ll Fri Jan 13 21:14:46 2017
@@ -5,15 +5,15 @@
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc"
-; CHECK: <lto object>:
-; CHECK: foo
+; CHECK: <lto object>
+; CHECK-NEXT: foo
define void @foo() {
call void @bar()
ret void
}
-; CHECK: <lto object>:
-; CHECK: bar
+; CHECK: <lto object>
+; CHECK-NEXT: bar
define void @bar() {
call void @foo()
ret void
Modified: lld/trunk/test/COFF/weak-external.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/weak-external.test?rev=291990&r1=291989&r2=291990&view=diff
==============================================================================
--- lld/trunk/test/COFF/weak-external.test (original)
+++ lld/trunk/test/COFF/weak-external.test Fri Jan 13 21:14:46 2017
@@ -4,9 +4,8 @@
# RUN: lld-link /out:%t2.exe /entry:g /subsystem:console /lldmap:%t2.map %t.obj %t.lto.obj
# RUN: FileCheck %s < %t2.map
-# CHECK: <lto object>:
-# CHECK-NOT: :
-# CHECK: {{ g$}}
+# CHECK: <lto object>
+# CHECK-NEXT: 0 g
--- !COFF
header:
Modified: lld/trunk/test/COFF/weak-external3.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/weak-external3.test?rev=291990&r1=291989&r2=291990&view=diff
==============================================================================
--- lld/trunk/test/COFF/weak-external3.test (original)
+++ lld/trunk/test/COFF/weak-external3.test Fri Jan 13 21:14:46 2017
@@ -5,13 +5,11 @@
# RUN: lld-link /out:%t2.exe /entry:f /subsystem:console /lldmap:%t2.map %t.obj %t.lto.obj
# RUN: FileCheck --check-prefix=CHECK2 %s < %t2.map
-# CHECK1: <lto object>:
-# CHECK1-NOT: :
-# CHECK1: {{ g$}}
+# CHECK1: <lto object>
+# CHECK1-NEXT: 0 g
-# CHECK2: weak-external3{{.*}}:
-# CHECK2-NOT: :
-# CHECK2: {{ f$}}
+# CHECK2: weak-external3.test.tmp.obj
+# CHECK2-NEXT: 0 f
--- !COFF
header:
More information about the llvm-commits
mailing list