[lld] r193454 - [PECOFF] Parse /merge command line option.

Rui Ueyama ruiu at google.com
Fri Oct 25 17:46:57 PDT 2013


Author: ruiu
Date: Fri Oct 25 19:46:57 2013
New Revision: 193454

URL: http://llvm.org/viewvc/llvm-project?rev=193454&view=rev
Log:
[PECOFF] Parse /merge command line option.

/merge:<from>=<to> option makes the linker to combine "from" section to "to"
section. This patch is to parse the option. The actual feature will be
implemented in a subsequent patch.

Modified:
    lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
    lld/trunk/lib/Driver/WinLinkDriver.cpp
    lld/trunk/lib/Driver/WinLinkOptions.td
    lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
    lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp

Modified: lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h?rev=193454&r1=193453&r2=193454&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h Fri Oct 25 19:46:57 2013
@@ -10,6 +10,7 @@
 #ifndef LLD_READER_WRITER_PECOFF_LINKER_CONTEXT_H
 #define LLD_READER_WRITER_PECOFF_LINKER_CONTEXT_H
 
+#include <map>
 #include <set>
 #include <vector>
 
@@ -184,6 +185,10 @@ public:
   void setImageType(ImageType type) { _imageType = type; }
   ImageType getImageType() const { return _imageType; }
 
+  StringRef getFinalSectionName(StringRef sectionName) const;
+  bool addSectionRenaming(raw_ostream &diagnostics,
+                          StringRef from, StringRef to);
+
   void addNoDefaultLib(StringRef libName) { _noDefaultLibs.insert(libName); }
   const std::set<std::string> &getNoDefaultLibs() const {
     return _noDefaultLibs;
@@ -255,6 +260,11 @@ private:
   std::unique_ptr<Reader> _reader;
   std::unique_ptr<Writer> _writer;
 
+  // A map for section renaming. For example, if there is an entry in the map
+  // whose value is .rdata -> .text, the section contens of .rdata will be
+  // merged to .text in the resulting executable.
+  std::map<std::string, std::string> _renamedSections;
+
   // List of files that will be removed on destruction.
   std::vector<std::unique_ptr<llvm::FileRemover> > _tempFiles;
 };

Modified: lld/trunk/lib/Driver/WinLinkDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=193454&r1=193453&r2=193454&view=diff
==============================================================================
--- lld/trunk/lib/Driver/WinLinkDriver.cpp (original)
+++ lld/trunk/lib/Driver/WinLinkDriver.cpp Fri Oct 25 19:46:57 2013
@@ -627,6 +627,20 @@ WinLinkDriver::parse(int argc, const cha
       break;
     }
 
+    case OPT_merge: {
+      // Parse /merge:<from>=<to>.
+      StringRef from, to;
+      llvm::tie(from, to) = StringRef(inputArg->getValue()).split('=');
+      if (from.empty() || to.empty()) {
+        diagnostics << "error: malformed /merge option: "
+                    << inputArg->getValue() << "\n";
+        return false;
+      }
+      if (!ctx.addSectionRenaming(diagnostics, from, to))
+        return false;
+      break;
+    }
+
     case OPT_subsystem: {
       // Parse /subsystem command line option. The form of /subsystem is
       // "subsystem_name[,majorOSVersion[.minorOSVersion]]".

Modified: lld/trunk/lib/Driver/WinLinkOptions.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkOptions.td?rev=193454&r1=193453&r2=193454&view=diff
==============================================================================
--- lld/trunk/lib/Driver/WinLinkOptions.td (original)
+++ lld/trunk/lib/Driver/WinLinkOptions.td Fri Oct 25 19:46:57 2013
@@ -29,6 +29,7 @@ def out     : P<"out", "Path to file to
 def stack   : P<"stack", "Size of the stack">;
 def machine : P<"machine", "Specify target platform">;
 def version : P<"version", "Specify a version number in the PE header">;
+def merge   : P<"merge", "Combine sections">;
 def subsystem : P<"subsystem", "Specify subsystem">;
 
 def manifest : F<"manifest">;

Modified: lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=193454&r1=193453&r2=193454&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp Fri Oct 25 19:46:57 2013
@@ -23,6 +23,7 @@
 #include "lld/ReaderWriter/Writer.h"
 
 #include <bitset>
+#include <set>
 
 namespace lld {
 
@@ -101,6 +102,58 @@ bool PECOFFLinkingContext::createImplici
   return true;
 }
 
+/// Returns the section name in the resulting executable.
+///
+/// Sections in object files are usually output to the executable with the same
+/// name, but you can rename by command line option. /merge:from=to makes the
+/// linker to combine "from" section contents to "to" section in the
+/// executable. We have a mapping for the renaming. This method looks up the
+/// table and returns a new section name if renamed.
+StringRef
+PECOFFLinkingContext::getFinalSectionName(StringRef sectionName) const {
+  auto it = _renamedSections.find(sectionName);
+  if (it == _renamedSections.end())
+    return sectionName;
+  return getFinalSectionName(it->second);
+}
+
+/// Adds a mapping to the section renaming table. This method will be used for
+/// /merge command line option.
+bool PECOFFLinkingContext::addSectionRenaming(raw_ostream &diagnostics,
+                                              StringRef from, StringRef to) {
+  auto it = _renamedSections.find(from);
+  if (it != _renamedSections.end()) {
+    if (it->second == to)
+      // There's already the same mapping.
+      return true;
+    diagnostics << "Section \"" << from << "\" is already mapped to \""
+                << it->second << ", so it cannot be mapped to \"" << to << "\".";
+    return true;
+  }
+
+  // Add a mapping, and check if there's no cycle in the renaming mapping. The
+  // cycle detection algorithm we use here is naive, but that's OK because the
+  // number of mapping is usually less than 10.
+  _renamedSections[from] = to;
+  for (auto elem : _renamedSections) {
+    StringRef sectionName = elem.first;
+    std::set<StringRef> visited;
+    visited.insert(sectionName);
+    for (;;) {
+      auto it = _renamedSections.find(sectionName);
+      if (it == _renamedSections.end())
+        break;
+      if (visited.count(it->second)) {
+        diagnostics << "/merge:" << from << "=" << to << " makes a cycle";
+        return false;
+      }
+      sectionName = it->second;
+      visited.insert(sectionName);
+    }
+  }
+  return true;
+}
+
 /// Try to find the input library file from the search paths and append it to
 /// the input file list. Returns true if the library file is found.
 StringRef PECOFFLinkingContext::searchLibraryFile(StringRef filename) const {

Modified: lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp?rev=193454&r1=193453&r2=193454&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp (original)
+++ lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp Fri Oct 25 19:46:57 2013
@@ -233,6 +233,19 @@ TEST_F(WinLinkParserTest, Include) {
   EXPECT_EQ("foo", symbols[0]);
 }
 
+TEST_F(WinLinkParserTest, Merge) {
+  EXPECT_TRUE(parse("link.exe", "/merge:.foo=.bar", "/merge:.bar=.baz",
+                    "a.out", nullptr));
+  EXPECT_EQ(".baz", _context.getFinalSectionName(".foo"));
+  EXPECT_EQ(".baz", _context.getFinalSectionName(".bar"));
+  EXPECT_EQ(".abc", _context.getFinalSectionName(".abc"));
+}
+
+TEST_F(WinLinkParserTest, Merge_Circular) {
+  EXPECT_FALSE(parse("link.exe", "/merge:.foo=.bar", "/merge:.bar=.foo",
+                     "a.out", nullptr));
+}
+
 //
 // Tests for /defaultlib and /nodefaultlib.
 //





More information about the llvm-commits mailing list