[lld] r195882 - [PECOFF] Improve /merge option handling.

Rui Ueyama ruiu at google.com
Wed Nov 27 13:34:16 PST 2013


Author: ruiu
Date: Wed Nov 27 15:34:16 2013
New Revision: 195882

URL: http://llvm.org/viewvc/llvm-project?rev=195882&view=rev
Log:
[PECOFF] Improve /merge option handling.

/MERGE option is a bit complicated for many reasons. Firstly, it takes both
positive and negative arguments. That means we have to have one of three
distinctive values (set, clear or unchange) for each permission bit. In this
patch we represent the three values using two bitmasks.

Secondly, the permissions specified by the parameter is bitwise or-ed with the
default permissions of a section. There is an exception for that rule; if one
of READ, WRITE or EXECUTE bit is specified, unspecified bits need to be
cleared. (So if you specify only WRITE for example, the resulting section will
not have WRITE nor EXECUTE bits.)

Lastly, multiple /merge options are allowed.

Modified:
    lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
    lld/trunk/lib/Driver/WinLinkDriver.cpp
    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=195882&r1=195881&r2=195882&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h Wed Nov 27 15:34:16 2013
@@ -19,7 +19,6 @@
 #include "lld/ReaderWriter/Writer.h"
 
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/COFF.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -209,25 +208,9 @@ public:
   virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
   virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
 
-  void setSectionAttributes(StringRef sectionName, uint32_t flags) {
-    _sectionAttributes[sectionName] = flags;
-  }
-
-  llvm::Optional<uint32_t> getSectionAttributes(StringRef sectionName) const {
-    auto it = _sectionAttributes.find(sectionName);
-    if (it == _sectionAttributes.end())
-      return llvm::None;
-    return it->second;
-  }
-
-  void setSectionAttributeMask(StringRef sectionName, uint32_t flags) {
-    _sectionAttributeMask[sectionName] = flags;
-  }
-
-  uint32_t getSectionAttributeMask(StringRef sectionName) const {
-    auto it = _sectionAttributeMask.find(sectionName);
-    return it == _sectionAttributeMask.end() ? 0 : it->second;
-  }
+  void setSectionSetMask(StringRef sectionName, uint32_t flags);
+  void setSectionClearMask(StringRef sectionName, uint32_t flags);
+  uint32_t getSectionAttributes(StringRef sectionName, uint32_t flags) const;
 
   void setDosStub(ArrayRef<uint8_t> data) { _dosStub = data; }
   ArrayRef<uint8_t> getDosStub() const { return _dosStub; }
@@ -304,14 +287,9 @@ private:
   // merged to .text in the resulting executable.
   std::map<std::string, std::string> _renamedSections;
 
-  // Section attributes specified by /section option. The uint32_t value will be
-  // copied to the Characteristics field of the section header.
-  std::map<std::string, uint32_t> _sectionAttributes;
-
-  // Section attributes specified by /section option in conjunction with the
-  // negative flag "!". The uint32_t value is a mask of section attributes that
-  // should be disabled.
-  std::map<std::string, uint32_t> _sectionAttributeMask;
+  // Section attributes specified by /section option.
+  std::map<std::string, uint32_t> _sectionSetMask;
+  std::map<std::string, uint32_t> _sectionClearMask;
 
   // 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=195882&r1=195881&r2=195882&view=diff
==============================================================================
--- lld/trunk/lib/Driver/WinLinkDriver.cpp (original)
+++ lld/trunk/lib/Driver/WinLinkDriver.cpp Wed Nov 27 15:34:16 2013
@@ -723,9 +723,9 @@ WinLinkDriver::parse(int argc, const cha
         return false;
       }
       if (flags.hasValue())
-        ctx.setSectionAttributes(section, *flags);
+        ctx.setSectionSetMask(section, *flags);
       if (mask.hasValue())
-        ctx.setSectionAttributeMask(section, *mask);
+        ctx.setSectionClearMask(section, *mask);
       break;
     }
 

Modified: lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=195882&r1=195881&r2=195882&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp Wed Nov 27 15:34:16 2013
@@ -204,6 +204,34 @@ PECOFFLinkingContext::stringFromRelocKin
   return make_error_code(YamlReaderError::illegal_value);
 }
 
+void PECOFFLinkingContext::setSectionSetMask(StringRef sectionName,
+                                             uint32_t newFlags) {
+  _sectionSetMask[sectionName] |= newFlags;
+  _sectionClearMask[sectionName] &= ~newFlags;
+  const uint32_t rwx = (llvm::COFF::IMAGE_SCN_MEM_READ |
+                        llvm::COFF::IMAGE_SCN_MEM_WRITE |
+                        llvm::COFF::IMAGE_SCN_MEM_EXECUTE);
+  if (newFlags & rwx)
+    _sectionClearMask[sectionName] |= ~_sectionSetMask[sectionName] & rwx;
+  assert((_sectionSetMask[sectionName] & _sectionClearMask[sectionName]) == 0);
+}
+
+void PECOFFLinkingContext::setSectionClearMask(StringRef sectionName,
+                                               uint32_t newFlags) {
+  _sectionClearMask[sectionName] |= newFlags;
+  _sectionSetMask[sectionName] &= ~newFlags;
+  assert((_sectionSetMask[sectionName] & _sectionClearMask[sectionName]) == 0);
+}
+
+uint32_t PECOFFLinkingContext::getSectionAttributes(StringRef sectionName,
+                                                    uint32_t flags) const {
+  auto si = _sectionSetMask.find(sectionName);
+  uint32_t setMask = (si == _sectionSetMask.end()) ? 0 : si->second;
+  auto ci = _sectionClearMask.find(sectionName);
+  uint32_t clearMask = (ci == _sectionClearMask.end()) ? 0 : ci->second;
+  return (flags | setMask) & ~clearMask;
+}
+
 void PECOFFLinkingContext::addPasses(PassManager &pm) {
   pm.add(std::unique_ptr<Pass>(new pecoff::SetSubsystemPass(*this)));
   pm.add(std::unique_ptr<Pass>(new pecoff::GroupedSectionsPass()));

Modified: lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp?rev=195882&r1=195881&r2=195882&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp (original)
+++ lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp Wed Nov 27 15:34:16 2013
@@ -275,43 +275,41 @@ const uint32_t execute = llvm::COFF::IMA
 const uint32_t read = llvm::COFF::IMAGE_SCN_MEM_READ;
 const uint32_t write = llvm::COFF::IMAGE_SCN_MEM_WRITE;
 
-TEST_F(WinLinkParserTest, Section) {
-  EXPECT_TRUE(parse("link.exe", "/section:.teXT,dekpRSW", "a.obj", nullptr));
-  uint32_t expect =
-      discardable | not_cached | not_paged | shared | execute | read | write;
-  llvm::Optional<uint32_t> val = _context.getSectionAttributes(".teXT");
-  EXPECT_TRUE(val.hasValue());
-  EXPECT_EQ(expect, *val);
-  EXPECT_EQ(0U, _context.getSectionAttributeMask(".teXT"));
-}
-
-TEST_F(WinLinkParserTest, SectionNegative) {
-  EXPECT_TRUE(parse("link.exe", "/section:.teXT,!dekpRSW", "a.obj", nullptr));
-  llvm::Optional<uint32_t> val = _context.getSectionAttributes(".teXT");
-  EXPECT_FALSE(val.hasValue());
-
-  uint32_t expect =
-      discardable | not_cached | not_paged | shared | execute | read | write;
-  EXPECT_EQ(expect, _context.getSectionAttributeMask(".teXT"));
-}
-
-#define TEST_SECTION(testname, arg, expect)                                  \
-  TEST_F(WinLinkParserTest, testname) {                                      \
-    EXPECT_TRUE(parse("link.exe", "/section:.text," arg, "a.obj", nullptr)); \
-    llvm::Optional<uint32_t> val = _context.getSectionAttributes(".text");   \
-    EXPECT_TRUE(val.hasValue());                                             \
-    EXPECT_EQ(expect, *val);                                                 \
+#define TEST_SECTION(testname, arg, expect)                                    \
+  TEST_F(WinLinkParserTest, testname) {                                        \
+    EXPECT_TRUE(parse("link.exe", "/section:.text," arg, "a.obj", nullptr));   \
+    EXPECT_EQ(expect, _context.getSectionAttributes(".text", execute | read)); \
   }
 
-TEST_SECTION(SectionD, "d", discardable);
+TEST_SECTION(SectionD, "d", execute | read | discardable);
 TEST_SECTION(SectionE, "e", execute);
-TEST_SECTION(SectionK, "k", not_cached);
-TEST_SECTION(SectionP, "p", not_paged);
+TEST_SECTION(SectionK, "k", execute | read | not_cached);
+TEST_SECTION(SectionP, "p", execute | read | not_paged);
 TEST_SECTION(SectionR, "r", read);
-TEST_SECTION(SectionS, "s", shared);
+TEST_SECTION(SectionS, "s", execute | read | shared);
 TEST_SECTION(SectionW, "w", write);
 
 #undef TEST_SECTION
+
+TEST_F(WinLinkParserTest, Section) {
+  EXPECT_TRUE(parse("link.exe", "/section:.text,dekprsw",
+                    "/section:.text,!dekprsw", "a.obj", nullptr));
+  EXPECT_EQ(0U, _context.getSectionAttributes(".text", execute | read));
+}
+
+TEST_F(WinLinkParserTest, SectionNegate) {
+  EXPECT_TRUE(parse("link.exe", "/section:.text,!e", "a.obj", nullptr));
+  EXPECT_EQ(read, _context.getSectionAttributes(".text", execute | read));
+}
+
+TEST_F(WinLinkParserTest, SectionMultiple) {
+  EXPECT_TRUE(parse("link.exe", "/section:.foo,e", "/section:.foo,rw",
+                    "/section:.foo,!d", "a.obj", nullptr));
+  uint32_t flags = execute | read | not_paged | discardable;
+  uint32_t expected = execute | read | write | not_paged;
+  EXPECT_EQ(expected, _context.getSectionAttributes(".foo", flags));
+}
+
 } // end anonymous namespace
 
 //





More information about the llvm-commits mailing list