[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