[lld] r291958 - Implement -Map.
Rafael Espindola via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 13 13:05:47 PST 2017
Author: rafael
Date: Fri Jan 13 15:05:46 2017
New Revision: 291958
URL: http://llvm.org/viewvc/llvm-project?rev=291958&view=rev
Log:
Implement -Map.
The format is not exactly the same as the one in bfd since bfd always
follows a linker script and prints it along.
Added:
lld/trunk/ELF/MapFile.cpp
lld/trunk/ELF/MapFile.h
lld/trunk/test/ELF/Inputs/map-file2.s
lld/trunk/test/ELF/Inputs/map-file3.s
lld/trunk/test/ELF/Inputs/map-file4.s
lld/trunk/test/ELF/map-file.s
Modified:
lld/trunk/ELF/CMakeLists.txt
lld/trunk/ELF/Config.h
lld/trunk/ELF/Driver.cpp
lld/trunk/ELF/Options.td
lld/trunk/ELF/OutputSections.cpp
lld/trunk/ELF/OutputSections.h
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/CMakeLists.txt?rev=291958&r1=291957&r2=291958&view=diff
==============================================================================
--- lld/trunk/ELF/CMakeLists.txt (original)
+++ lld/trunk/ELF/CMakeLists.txt Fri Jan 13 15:05:46 2017
@@ -17,6 +17,7 @@ add_lld_library(lldELF
InputSection.cpp
LTO.cpp
LinkerScript.cpp
+ MapFile.cpp
MarkLive.cpp
Mips.cpp
OutputSections.cpp
Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=291958&r1=291957&r2=291958&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Fri Jan 13 15:05:46 2017
@@ -80,6 +80,7 @@ struct Configuration {
llvm::StringRef Init;
llvm::StringRef LTOAAPipeline;
llvm::StringRef LTONewPmPasses;
+ llvm::StringRef MapFile;
llvm::StringRef OutputFile;
llvm::StringRef SoName;
llvm::StringRef Sysroot;
Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=291958&r1=291957&r2=291958&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Fri Jan 13 15:05:46 2017
@@ -512,6 +512,7 @@ void LinkerDriver::readConfigs(opt::Inpu
Config->Init = getString(Args, OPT_init, "_init");
Config->LTOAAPipeline = getString(Args, OPT_lto_aa_pipeline);
Config->LTONewPmPasses = getString(Args, OPT_lto_newpm_passes);
+ Config->MapFile = getString(Args, OPT_Map);
Config->OutputFile = getString(Args, OPT_o);
Config->SoName = getString(Args, OPT_soname);
Config->Sysroot = getString(Args, OPT_sysroot);
Added: lld/trunk/ELF/MapFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MapFile.cpp?rev=291958&view=auto
==============================================================================
--- lld/trunk/ELF/MapFile.cpp (added)
+++ lld/trunk/ELF/MapFile.cpp Fri Jan 13 15:05:46 2017
@@ -0,0 +1,135 @@
+//===- 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 -Map 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 "InputFiles.h"
+#include "Strings.h"
+
+#include "llvm/Support/FileUtilities.h"
+
+using namespace llvm;
+using namespace llvm::object;
+
+using namespace lld;
+using namespace lld::elf;
+
+static void writeOutSecLine(raw_fd_ostream &OS, int Width, uint64_t Address,
+ uint64_t Size, uint64_t Align, StringRef Name) {
+ OS << format_hex_no_prefix(Address, Width) << ' '
+ << format_hex_no_prefix(Size, Width) << ' ' << format("%5x ", Align)
+ << left_justify(Name, 7);
+}
+
+static void writeInSecLine(raw_fd_ostream &OS, int Width, 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, Width, Address, Size, Align, "");
+ OS << ' ' << left_justify(Name, 7);
+}
+
+static void writeFileLine(raw_fd_ostream &OS, int Width, 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, Width, Address, Size, Align, "");
+ OS << ' ' << left_justify(Name, 7);
+}
+
+static void writeSymbolLine(raw_fd_ostream &OS, int Width, uint64_t Address,
+ uint64_t Size, StringRef Name) {
+ // Pass an empty name to align the text to the correct column.
+ writeFileLine(OS, Width, Address, Size, 0, "");
+ OS << ' ' << left_justify(Name, 7);
+}
+
+template <class ELFT>
+static void writeMapFile2(int FD,
+ ArrayRef<OutputSectionBase *> OutputSections) {
+ typedef typename ELFT::uint uintX_t;
+ raw_fd_ostream OS(FD, true);
+ int Width = ELFT::Is64Bits ? 16 : 8;
+ OS << left_justify("Address", Width) << ' ' << left_justify("Size", Width)
+ << ' ' << left_justify("Align", 5) << ' ' << left_justify("Out", 7) << ' '
+ << left_justify("In", 7) << ' ' << left_justify("File", 7) << " Symbol\n";
+ for (OutputSectionBase *Sec : OutputSections) {
+ uintX_t VA = Sec->Addr;
+ writeOutSecLine(OS, Width, VA, Sec->Size, Sec->Addralign, Sec->getName());
+ OS << '\n';
+ StringRef PrevName = "";
+ Sec->forEachInputSection([&](InputSectionData *S) {
+ const auto *IS = dyn_cast<InputSection<ELFT>>(S);
+ if (!IS)
+ return;
+ StringRef Name = IS->Name;
+ if (Name != PrevName) {
+ writeInSecLine(OS, Width, VA + IS->OutSecOff, IS->getSize(),
+ IS->Alignment, Name);
+ OS << '\n';
+ PrevName = Name;
+ }
+ elf::ObjectFile<ELFT> *File = IS->getFile();
+ if (!File)
+ return;
+ writeFileLine(OS, Width, VA + IS->OutSecOff, IS->getSize(), IS->Alignment,
+ toString(File));
+ OS << '\n';
+ ArrayRef<SymbolBody *> Syms = File->getSymbols();
+ for (SymbolBody *Sym : Syms) {
+ auto *DR = dyn_cast<DefinedRegular<ELFT>>(Sym);
+ if (!DR)
+ continue;
+ if (DR->Section != IS)
+ continue;
+ if (DR->isSection())
+ continue;
+ writeSymbolLine(OS, Width, Sym->getVA<ELFT>(), Sym->getSize<ELFT>(),
+ toString(*Sym));
+ OS << '\n';
+ }
+ });
+ }
+}
+
+template <class ELFT>
+void elf::writeMapFile(ArrayRef<OutputSectionBase *> 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<ELFT>(FD, OutputSections);
+ EC = sys::fs::rename(TempPath, MapFile);
+ if (EC)
+ fatal(EC.message());
+}
+
+template void elf::writeMapFile<ELF32LE>(ArrayRef<OutputSectionBase *>);
+template void elf::writeMapFile<ELF32BE>(ArrayRef<OutputSectionBase *>);
+template void elf::writeMapFile<ELF64LE>(ArrayRef<OutputSectionBase *>);
+template void elf::writeMapFile<ELF64BE>(ArrayRef<OutputSectionBase *>);
Added: lld/trunk/ELF/MapFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MapFile.h?rev=291958&view=auto
==============================================================================
--- lld/trunk/ELF/MapFile.h (added)
+++ lld/trunk/ELF/MapFile.h Fri Jan 13 15:05: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_ELF_MAPFILE_H
+#define LLD_ELF_MAPFILE_H
+
+#include "OutputSections.h"
+
+namespace lld {
+namespace elf {
+template <class ELFT>
+void writeMapFile(llvm::ArrayRef<OutputSectionBase *> OutputSections);
+}
+}
+
+#endif
Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=291958&r1=291957&r2=291958&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Fri Jan 13 15:05:46 2017
@@ -121,6 +121,8 @@ def lto_O: J<"lto-O">, MetaVarName<"<opt
def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target emulation">;
+def Map: JS<"Map">;
+
def nostdlib: F<"nostdlib">,
HelpText<"Only search directories specified on the command line">;
@@ -269,6 +271,7 @@ def alias_format_b: S<"b">, Alias<format
def alias_hash_style_hash_style: J<"hash-style=">, Alias<hash_style>;
def alias_init_init: J<"init=">, Alias<init>;
def alias_l__library: J<"library=">, Alias<l>;
+def alias_Map_eq: J<"Map=">, Alias<Map>;
def alias_omagic: Flag<["-"], "N">, Alias<omagic>;
def alias_o_output: Joined<["--"], "output=">, Alias<o>;
def alias_o_output2 : Separate<["--"], "output">, Alias<o>;
@@ -325,7 +328,6 @@ def demangle: F<"demangle">;
def detect_odr_violations: F<"detect-odr-violations">;
def g: Flag<["-"], "g">;
def M: Flag<["-"], "M">;
-def Map: JS<"Map">;
def no_add_needed: F<"no-add-needed">;
def no_allow_shlib_undefined: F<"no-allow-shlib-undefined">;
def no_copy_dt_needed_entries: F<"no-copy-dt-needed-entries">,
@@ -350,7 +352,6 @@ def Qy : F<"Qy">;
def alias_define_common_d: Flag<["-"], "d">, Alias<define_common>;
def alias_define_common_dc: F<"dc">, Alias<define_common>;
def alias_define_common_dp: F<"dp">, Alias<define_common>;
-def alias_Map_eq: J<"Map=">, Alias<Map>;
def alias_version_script_version_script: J<"version-script=">,
Alias<version_script>;
Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=291958&r1=291957&r2=291958&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Fri Jan 13 15:05:46 2017
@@ -139,6 +139,13 @@ void OutputSection<ELFT>::addSection(Inp
this->Entsize = S->Entsize;
}
+template <class ELFT>
+void OutputSection<ELFT>::forEachInputSection(
+ std::function<void(InputSectionData *)> F) {
+ for (InputSection<ELFT> *S : Sections)
+ F(S);
+}
+
// This function is called after we sort input sections
// and scan relocations to setup sections' offsets.
template <class ELFT> void OutputSection<ELFT>::assignOffsets() {
@@ -265,6 +272,13 @@ template <class ELFT>
EhOutputSection<ELFT>::EhOutputSection()
: OutputSectionBase(".eh_frame", SHT_PROGBITS, SHF_ALLOC) {}
+template <class ELFT>
+void EhOutputSection<ELFT>::forEachInputSection(
+ std::function<void(InputSectionData *)> F) {
+ for (EhInputSection<ELFT> *S : Sections)
+ F(S);
+}
+
// Search for an existing CIE record or create a new one.
// CIE records from input object files are uniquified by their contents
// and where their relocations point to.
Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=291958&r1=291957&r2=291958&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Fri Jan 13 15:05:46 2017
@@ -81,6 +81,7 @@ public:
OutputSectionBase *FirstInPtLoad = nullptr;
virtual void finalize() {}
+ virtual void forEachInputSection(std::function<void(InputSectionData *)> F) {}
virtual void assignOffsets() {}
virtual void writeTo(uint8_t *Buf) {}
virtual ~OutputSectionBase() = default;
@@ -116,6 +117,7 @@ public:
void sortCtorsDtors();
void writeTo(uint8_t *Buf) override;
void finalize() override;
+ void forEachInputSection(std::function<void(InputSectionData *)> F) override;
void assignOffsets() override;
Kind getKind() const override { return Regular; }
static bool classof(const OutputSectionBase *B) {
@@ -168,6 +170,7 @@ public:
void writeTo(uint8_t *Buf) override;
void finalize() override;
bool empty() const { return Sections.empty(); }
+ void forEachInputSection(std::function<void(InputSectionData *)> F) override;
void addSection(InputSectionData *S) override;
Kind getKind() const override { return EHFrame; }
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=291958&r1=291957&r2=291958&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Fri Jan 13 15:05:46 2017
@@ -10,6 +10,7 @@
#include "Writer.h"
#include "Config.h"
#include "LinkerScript.h"
+#include "MapFile.h"
#include "Memory.h"
#include "OutputSections.h"
#include "Relocations.h"
@@ -233,6 +234,7 @@ template <class ELFT> void Writer<ELFT>:
if (ErrorCount)
return;
+ writeMapFile<ELFT>(OutputSections);
if (auto EC = Buffer->commit())
error("failed to write to the output file: " + EC.message());
Added: lld/trunk/test/ELF/Inputs/map-file2.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/map-file2.s?rev=291958&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/map-file2.s (added)
+++ lld/trunk/test/ELF/Inputs/map-file2.s Fri Jan 13 15:05:46 2017
@@ -0,0 +1,8 @@
+foo:
+nop
+.global bar
+bar:
+nop
+.section .text.zed,"ax", at progbits
+.global zed
+zed:
Added: lld/trunk/test/ELF/Inputs/map-file3.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/map-file3.s?rev=291958&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/map-file3.s (added)
+++ lld/trunk/test/ELF/Inputs/map-file3.s Fri Jan 13 15:05:46 2017
@@ -0,0 +1,2 @@
+.global bah
+bah:
Added: lld/trunk/test/ELF/Inputs/map-file4.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/map-file4.s?rev=291958&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/map-file4.s (added)
+++ lld/trunk/test/ELF/Inputs/map-file4.s Fri Jan 13 15:05:46 2017
@@ -0,0 +1,3 @@
+.global baz
+baz:
+ retq
Added: lld/trunk/test/ELF/map-file.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/map-file.s?rev=291958&view=auto
==============================================================================
--- lld/trunk/test/ELF/map-file.s (added)
+++ lld/trunk/test/ELF/map-file.s Fri Jan 13 15:05:46 2017
@@ -0,0 +1,54 @@
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/map-file2.s -o %t2.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/map-file3.s -o %t3.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/map-file4.s -o %t4.o
+// RUN: rm -f %t4.a
+// RUN: llvm-ar rc %t4.a %t4.o
+// RUN: ld.lld %t1.o %t2.o %t3.o %t4.a -o %t -Map=%t.map
+// RUN: FileCheck %s < %t.map
+
+.global _start
+_start:
+ call baz
+.global _Z1fi
+_Z1fi:
+.cfi_startproc
+.cfi_endproc
+nop
+.weak bar
+bar:
+.long bar - .
+.long zed - .
+local:
+.comm common,4,4
+
+// CHECK: Address Size Align Out In File Symbol
+// CHECK-NEXT: 0000000000200158 0000000000000030 8 .eh_frame
+// CHECK-NEXT: 0000000000201000 0000000000000015 4 .text
+// CHECK-NEXT: 0000000000201000 000000000000000e 4 .text
+// CHECK-NEXT: 0000000000201000 000000000000000e 4 {{.*}}/map-file.s.tmp1.o
+// CHECK-NEXT: 000000000020100e 0000000000000000 0 local
+// CHECK-NEXT: 0000000000201005 0000000000000000 0 f(int)
+// CHECK-NEXT: 0000000000201000 0000000000000000 0 _start
+// CHECK-NEXT: 0000000000201010 0000000000000002 4 {{.*}}/map-file.s.tmp2.o
+// CHECK-NEXT: 0000000000201010 0000000000000000 0 foo
+// CHECK-NEXT: 0000000000201011 0000000000000000 0 bar
+// CHECK-NEXT: 0000000000201012 0000000000000000 1 .text.zed
+// CHECK-NEXT: 0000000000201012 0000000000000000 1 {{.*}}/map-file.s.tmp2.o
+// CHECK-NEXT: 0000000000201012 0000000000000000 0 zed
+// CHECK-NEXT: 0000000000201014 0000000000000000 4 .text
+// CHECK-NEXT: 0000000000201014 0000000000000000 4 {{.*}}/map-file.s.tmp3.o
+// CHECK-NEXT: 0000000000201014 0000000000000000 0 bah
+// CHECK-NEXT: 0000000000201014 0000000000000001 4 {{.*}}/map-file.s.tmp4.a(map-file.s.tmp4.o)
+// CHECK-NEXT: 0000000000201014 0000000000000000 0 baz
+// CHECK-NEXT: 0000000000202000 0000000000000004 4 .bss
+// CHECK-NEXT: 0000000000202000 0000000000000004 4 COMMON
+// CHECK-NEXT: 0000000000000000 0000000000000008 1 .comment
+// CHECK-NEXT: 0000000000000000 00000000000000f0 8 .symtab
+// CHECK-NEXT: 0000000000000000 00000000000000f0 8 .symtab
+// CHECK-NEXT: 0000000000000000 0000000000000039 1 .shstrtab
+// CHECK-NEXT: 0000000000000000 0000000000000039 1 .shstrtab
+// CHECK-NEXT: 0000000000000000 000000000000002f 1 .strtab
+// CHECK-NEXT: 0000000000000000 000000000000002f 1 .strtab
More information about the llvm-commits
mailing list