[PATCH] [PECOFF] Connect defined atoms with layout before/after edges.

Rui Ueyama ruiu at google.com
Sun Jun 16 20:59:35 PDT 2013


Hi shankarke,

I don't think there's an easy way to test this change because it wouldn't
change the order of atoms now. Previously we didn't have the layout pass for
the PE/COFF writer, and we emitted all the atoms in the same order as they
appeared in input object files, which is the same order with this patch.

I'm writing a new patch to merge sections. In PE/COFF, the linker is expected
to merge sections by discarding the dollar prefix. Thus, if there are sections
named .text$1 and .text$2, they will be merged to .text.

The characters following the dollar sign determines the ordering of the
sections. Naturally that should be modeled by the atom model in lld.
I think we will be able to test the layout pass in the next patch.

http://llvm-reviews.chandlerc.com/D989

Files:
  include/lld/ReaderWriter/PECOFFTargetInfo.h
  lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp
  lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
  lib/ReaderWriter/PECOFF/WriterPECOFF.cpp

Index: include/lld/ReaderWriter/PECOFFTargetInfo.h
===================================================================
--- include/lld/ReaderWriter/PECOFFTargetInfo.h
+++ include/lld/ReaderWriter/PECOFFTargetInfo.h
@@ -41,7 +41,7 @@
   virtual Writer &writer() const;
   virtual bool validateImpl(raw_ostream &diagnostics);
 
-  virtual void addPasses(PassManager &pm) const {}
+  virtual void addPasses(PassManager &pm) const;
 
   void setStackReserve(uint64_t size) { _stackReserve = size; }
   void setStackCommit(uint64_t size) { _stackCommit = size; }
Index: lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp
===================================================================
--- lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp
+++ lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp
@@ -9,6 +9,8 @@
 
 #include "lld/ReaderWriter/PECOFFTargetInfo.h"
 
+#include "lld/Core/PassManager.h"
+#include "lld/Passes/LayoutPass.h"
 #include "lld/ReaderWriter/Reader.h"
 #include "lld/ReaderWriter/Writer.h"
 
@@ -56,4 +58,8 @@
   return make_error_code(yaml_reader_error::illegal_value);
 }
 
+void PECOFFTargetInfo::addPasses(PassManager &pm) const {
+  pm.add(std::unique_ptr<Pass>(new LayoutPass()));
+}
+
 } // end namespace lld
Index: lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
===================================================================
--- lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
+++ lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
@@ -41,6 +41,10 @@
 /// to be fixed up so that the address points to atom Y's address.
 class COFFReference LLVM_FINAL : public Reference {
 public:
+  COFFReference(Kind kind) : _target(nullptr), _offsetInAtom(0) {
+    _kind = kind;
+  }
+
   COFFReference(const Atom *target, uint32_t offsetInAtom, uint16_t relocType)
       : _target(target), _offsetInAtom(offsetInAtom) {
     setKind(static_cast<Reference::Kind>(relocType));
@@ -431,6 +435,38 @@
     return error_code::success();
   }
 
+  void addEdge(COFFDefinedAtom *a, COFFDefinedAtom *b,
+               lld::Reference::Kind kind) const {
+    auto ref = new (AtomStorage.Allocate<COFFReference>()) COFFReference(kind);
+    ref->setTarget(b);
+    a->addReference(ref);
+  }
+
+  void connectAtomsWithLayoutEdge(COFFDefinedAtom *a,
+                                  COFFDefinedAtom *b) const {
+    addEdge(a, b, lld::Reference::kindLayoutAfter);
+    addEdge(b, a, lld::Reference::kindLayoutBefore);
+  }
+
+  /// Connect atoms appeared in the same section with layout-{before,after}
+  /// edges. It has two purposes.
+  ///
+  ///   - To prevent atoms from being GC'ed (aka dead-stripped) if there is a
+  ///     reference to one of the atoms. In that case we want to emit all the
+  ///     atoms appeared in the same section, because the referenced "live"
+  ///     atom may reference other atoms in the same section. If we don't add
+  ///     edges between atoms, unreferenced atoms in the same section would be
+  ///     GC'ed.
+  ///   - To preserve the order of atmos. We want to emit the atoms in the
+  ///     same order as they appeared in the input object file.
+  void addLayoutEdges(vector<COFFDefinedAtom *> &definedAtoms) const {
+    if (definedAtoms.size() <= 1)
+      return;
+    for (auto it = definedAtoms.begin(), e = definedAtoms.end(); it + 1 != e;
+         ++it)
+      connectAtomsWithLayoutEdge(*it, *(it + 1));
+  }
+
   error_code AtomizeDefinedSymbols(SectionToSymbolsT &definedSymbols,
                                    vector<const DefinedAtom *> &definedAtoms,
                                    SymbolNameToAtomT &symbolToAtom,
@@ -445,6 +481,9 @@
               AtomizeDefinedSymbolsInSection(section, symbols, atoms))
         return ec;
 
+      // Connect atoms with layout-before/layout-after edges.
+      addLayoutEdges(atoms);
+
       for (COFFDefinedAtom *atom : atoms) {
         if (!atom->name().empty())
           symbolToAtom[atom->name()] = atom;
Index: lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
===================================================================
--- lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
+++ lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
@@ -336,6 +336,11 @@
         auto relocSite = reinterpret_cast<llvm::support::ulittle32_t *>(
             fileBuffer + layout->_fileOffset + ref->offsetInAtom());
         uint64_t targetAddr = atomToVirtualAddr[ref->target()];
+
+        // Skip if this reference is not for relocation.
+        if (ref->kind() < lld::Reference::kindTargetLow)
+          continue;
+
         switch (ref->kind()) {
         case llvm::COFF::IMAGE_REL_I386_DIR32:
           *relocSite = targetAddr;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D989.1.patch
Type: text/x-patch
Size: 4586 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130616/b5b6f21b/attachment.bin>


More information about the llvm-commits mailing list