[lld] r193017 - [PECOFF] Only COMDAT symbols are allowed to be dead-stripped.

Rui Ueyama ruiu at google.com
Fri Oct 18 16:54:56 PDT 2013


Author: ruiu
Date: Fri Oct 18 18:54:55 2013
New Revision: 193017

URL: http://llvm.org/viewvc/llvm-project?rev=193017&view=rev
Log:
[PECOFF] Only COMDAT symbols are allowed to be dead-stripped.

We should dead-strip atoms only if they are created for COMDAT symbols. If we
remove non-COMDAT atoms from a binary, it will no longer be guaranteed that
the binary will work correctly.

In COFF, you can manipulate the order of section contents in the resulting
binary by section name. For example, if you have four sections
.data$unique_prefix_{a,b,c,d}, it's guaranteed that the contents of A, B, C,
and D will be consecutive in the resulting .data section in that order.
Thus, you can access B's and C's contents by incrementing a pointer pointing
to A until it reached to D. That's why we cannot dead-strip B or C even if
no one is directly referencing to them.

Some object files in the standard library actually use that technique.

Modified:
    lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h
    lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
    lld/trunk/test/pecoff/grouped-sections.test

Modified: lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h?rev=193017&r1=193016&r2=193017&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h Fri Oct 18 18:54:55 2013
@@ -181,17 +181,24 @@ private:
 class COFFDefinedAtom : public COFFDefinedFileAtom {
 public:
   COFFDefinedAtom(const File &file, StringRef name, StringRef sectionName,
-                  Scope scope, ContentType type, ContentPermissions perms,
-                  Merge merge, ArrayRef<uint8_t> data, uint64_t ordinal)
+                  Scope scope, ContentType type, bool isComdat,
+                  ContentPermissions perms, Merge merge, ArrayRef<uint8_t> data,
+                  uint64_t ordinal)
       : COFFDefinedFileAtom(file, name, sectionName, scope, type, perms,
                             ordinal),
-        _merge(merge), _dataref(data) {}
+        _isComdat(isComdat), _merge(merge), _dataref(data) {}
 
   virtual Merge merge() const { return _merge; }
   virtual uint64_t size() const { return _dataref.size(); }
   virtual ArrayRef<uint8_t> rawContent() const { return _dataref; }
 
+  virtual DeadStripKind deadStrip() const {
+    // Only COMDAT symbols would be dead-stripped.
+    return _isComdat ? deadStripNormal : deadStripNever;
+  }
+
 private:
+  bool _isComdat;
   Merge _merge;
   ArrayRef<uint8_t> _dataref;
 };

Modified: lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp?rev=193017&r1=193016&r2=193017&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp Fri Oct 18 18:54:55 2013
@@ -397,6 +397,8 @@ private:
       if (!(sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_COMDAT))
         continue;
 
+      _comdatSections.insert(sec);
+
       if (sym->NumberOfAuxSymbols == 0)
         return llvm::object::object_error::parse_failed;
       const coff_aux_section_definition *aux =
@@ -473,13 +475,14 @@ private:
 
     DefinedAtom::ContentType type = getContentType(section);
     DefinedAtom::ContentPermissions perms = getPermissions(section);
+    bool isComdat = (_comdatSections.count(section) == 1);
 
     // Create an atom for the entire section.
     if (symbols.empty()) {
       ArrayRef<uint8_t> data(secData.data(), secData.size());
       auto *atom = new (_alloc)
           COFFDefinedAtom(*this, "", sectionName, Atom::scopeTranslationUnit,
-                          type, perms, _merge[section], data, 0);
+                          type, isComdat, perms, _merge[section], data, 0);
       atoms.push_back(atom);
       _definedAtomLocations[section][0].push_back(atom);
       return error_code::success();
@@ -490,9 +493,9 @@ private:
     if (symbols[0]->Value != 0) {
       uint64_t size = symbols[0]->Value;
       ArrayRef<uint8_t> data(secData.data(), size);
-      auto *atom = new (_alloc)
-          COFFDefinedAtom(*this, "", sectionName, Atom::scopeTranslationUnit,
-                          type, perms, _merge[section], data, ++ordinal);
+      auto *atom = new (_alloc) COFFDefinedAtom(
+          *this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat,
+          perms, _merge[section], data, ++ordinal);
       atoms.push_back(atom);
       _definedAtomLocations[section][0].push_back(atom);
     }
@@ -503,9 +506,9 @@ private:
       const uint8_t *end = (si + 1 == se) ? secData.data() + secData.size()
                                           : secData.data() + (*(si + 1))->Value;
       ArrayRef<uint8_t> data(start, end);
-      auto *atom = new (_alloc)
-          COFFDefinedAtom(*this, _symbolName[*si], sectionName, getScope(*si),
-                          type, perms, _merge[section], data, ++ordinal);
+      auto *atom = new (_alloc) COFFDefinedAtom(
+          *this, _symbolName[*si], sectionName, getScope(*si), type, isComdat,
+          perms, _merge[section], data, ++ordinal);
       atoms.push_back(atom);
       _symbolAtom[*si] = atom;
       _definedAtomLocations[section][(*si)->Value].push_back(atom);
@@ -696,6 +699,9 @@ private:
   // A map from section to its atoms.
   std::map<const coff_section *, vector<COFFDefinedFileAtom *> > _sectionAtoms;
 
+  // A set of COMDAT sections.
+  std::set<const coff_section *> _comdatSections;
+
   // A map to get whether the section allows its contents to be merged or not.
   std::map<const coff_section *, DefinedAtom::Merge> _merge;
 

Modified: lld/trunk/test/pecoff/grouped-sections.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/grouped-sections.test?rev=193017&r1=193016&r2=193017&view=diff
==============================================================================
--- lld/trunk/test/pecoff/grouped-sections.test (original)
+++ lld/trunk/test/pecoff/grouped-sections.test Fri Oct 18 18:54:55 2013
@@ -1,6 +1,6 @@
 # RUN: yaml2obj %p/Inputs/grouped-sections.obj.yaml > %t.obj
 #
-# RUN: lld -flavor link /out:%t1 /subsystem:console /force /opt:noref \
+# RUN: lld -flavor link /out:%t1 /subsystem:console /force \
 # RUN:   -- %t.obj && llvm-objdump -s %t1 | FileCheck %s
 #
 # The file "grouped-sections.obj" has three data sections in the following





More information about the llvm-commits mailing list