[lld] r229762 - PECOFF: Fix symbol aliases

Rui Ueyama ruiu at google.com
Wed Feb 18 15:11:48 PST 2015


Author: ruiu
Date: Wed Feb 18 17:11:48 2015
New Revision: 229762

URL: http://llvm.org/viewvc/llvm-project?rev=229762&view=rev
Log:
PECOFF: Fix symbol aliases

Weak aliases defined using /alternatename command line option were getting
wrong RVAs in the final output because of wrong atom ordinal. Alias atoms
were assigned large ordinals than any other regular atoms because they were
instantiated after other atoms and just got new (larger) ordinals.

Atoms are sorted by its file and atom ordinals in the order pass. Alias
atoms were located after all other atoms in the same file.

An alias atom's ordinal needs to be smaller than its alias target but larger
than the atom appeared before the target -- so that the alias is located
between the two. Since an alias has no size, the alias target will be located
at the same location as the alias.

In this patch, I made a gap between two regular atoms so that we can put
aliases after instantiating them (without re-numbering existing atoms).

Modified:
    lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
    lld/trunk/test/pecoff/entry.test

Modified: lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp?rev=229762&r1=229761&r2=229762&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp Wed Feb 18 17:11:48 2015
@@ -83,7 +83,7 @@ public:
 
   FileCOFF(std::unique_ptr<MemoryBuffer> mb, PECOFFLinkingContext &ctx)
     : File(mb->getBufferIdentifier(), kindObject), _mb(std::move(mb)),
-      _compatibleWithSEH(false), _ordinal(0),
+      _compatibleWithSEH(false), _ordinal(1),
       _machineType(llvm::COFF::MT_Invalid), _ctx(ctx) {}
 
   std::error_code doParse() override;
@@ -108,11 +108,6 @@ public:
 
   void beforeLink() override;
 
-  void addDefinedAtom(AliasAtom *atom) {
-    atom->setOrdinal(_ordinal++);
-    _definedAtoms._atoms.push_back(atom);
-  }
-
   void addUndefinedSymbol(StringRef sym) {
     _undefinedAtoms._atoms.push_back(new (_alloc) COFFUndefinedAtom(*this, sym));
   }
@@ -168,6 +163,7 @@ private:
   std::error_code addRelocationReferenceToAtoms();
   std::error_code findSection(StringRef name, const coff_section *&result);
   StringRef ArrayRefToString(ArrayRef<uint8_t> array);
+  uint64_t getNextOrdinal();
 
   std::unique_ptr<const llvm::object::COFFObjectFile> _obj;
   std::unique_ptr<MemoryBuffer> _mb;
@@ -555,7 +551,7 @@ FileCOFF::createDefinedSymbols(const Sym
       uint32_t size = sym.getValue();
       auto *atom = new (_alloc)
           COFFBSSAtom(*this, name, getScope(sym), DefinedAtom::permRW_,
-                      DefinedAtom::mergeAsWeakAndAddressUsed, size, _ordinal++);
+                      DefinedAtom::mergeAsWeakAndAddressUsed, size, getNextOrdinal());
 
       // Common symbols should be aligned on natural boundaries with the maximum
       // of 32 byte. It's not documented anywhere, but it's what MSVC link.exe
@@ -669,7 +665,7 @@ std::error_code FileCOFF::AtomizeDefined
                                      : si[1].getValue() - sym.getValue();
       auto *atom = new (_alloc) COFFBSSAtom(
           *this, _symbolName[sym], getScope(sym), getPermissions(section),
-          DefinedAtom::mergeAsWeakAndAddressUsed, size, _ordinal++);
+          DefinedAtom::mergeAsWeakAndAddressUsed, size, getNextOrdinal());
       atoms.push_back(atom);
       _symbolAtom[sym] = atom;
     }
@@ -704,7 +700,7 @@ std::error_code FileCOFF::AtomizeDefined
     ArrayRef<uint8_t> data(secData.data(), secData.size());
     auto *atom = new (_alloc) COFFDefinedAtom(
         *this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat,
-        perms, _merge[section], data, _ordinal++);
+        perms, _merge[section], data, getNextOrdinal());
     atoms.push_back(atom);
     _definedAtomLocations[section][0].push_back(atom);
     return std::error_code();
@@ -717,7 +713,7 @@ std::error_code FileCOFF::AtomizeDefined
     ArrayRef<uint8_t> data(secData.data(), size);
     auto *atom = new (_alloc) COFFDefinedAtom(
         *this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat,
-        perms, _merge[section], data, _ordinal++);
+        perms, _merge[section], data, getNextOrdinal());
     atoms.push_back(atom);
     _definedAtomLocations[section][0].push_back(atom);
   }
@@ -730,7 +726,7 @@ std::error_code FileCOFF::AtomizeDefined
     ArrayRef<uint8_t> data(start, end);
     auto *atom = new (_alloc) COFFDefinedAtom(
         *this, _symbolName[*si], sectionName, getScope(*si), type, isComdat,
-        perms, _merge[section], data, _ordinal++);
+        perms, _merge[section], data, getNextOrdinal());
     atoms.push_back(atom);
     _symbolAtom[*si] = atom;
     _definedAtomLocations[section][si->getValue()].push_back(atom);
@@ -868,6 +864,7 @@ AliasAtom *FileCOFF::createAlias(StringR
   alias->setMerge(DefinedAtom::mergeAsWeak);
   if (target->contentType() == DefinedAtom::typeCode)
     alias->setDeadStrip(DefinedAtom::deadStripNever);
+  alias->setOrdinal(target->ordinal() - 1);
   return alias;
 }
 
@@ -879,7 +876,7 @@ void FileCOFF::createAlternateNameAtoms(
       aliases.push_back(createAlias(it->second, atom));
   }
   for (AliasAtom *alias : aliases)
-    addDefinedAtom(alias);
+    _definedAtoms._atoms.push_back(alias);
 }
 
 // Interpret the contents of .drectve section. If exists, the section contains
@@ -988,7 +985,7 @@ std::error_code FileCOFF::maybeCreateSXD
   auto *atom = new (_alloc) COFFDefinedAtom(
       *this, "", ".sxdata", Atom::scopeTranslationUnit, DefinedAtom::typeData,
       false /*isComdat*/, DefinedAtom::permR__, DefinedAtom::mergeNo,
-      sxdata, _ordinal++);
+      sxdata, getNextOrdinal());
 
   const ulittle32_t *symbolIndex =
       reinterpret_cast<const ulittle32_t *>(sxdata.data());
@@ -1064,6 +1061,13 @@ StringRef FileCOFF::ArrayRefToString(Arr
   return StringRef(*contents).trim();
 }
 
+// getNextOrdinal returns a monotonically increasaing uint64_t number
+// starting from 1. There's a large gap between two numbers returned
+// from this function, so that you can put other atoms between them.
+uint64_t FileCOFF::getNextOrdinal() {
+  return _ordinal++ << 32;
+}
+
 class COFFObjectReader : public Reader {
 public:
   COFFObjectReader(PECOFFLinkingContext &ctx) : _ctx(ctx) {}

Modified: lld/trunk/test/pecoff/entry.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/entry.test?rev=229762&r1=229761&r2=229762&view=diff
==============================================================================
--- lld/trunk/test/pecoff/entry.test (original)
+++ lld/trunk/test/pecoff/entry.test Wed Feb 18 17:11:48 2015
@@ -33,7 +33,7 @@ WWINMAIN: _wWinMainCRTStartup
 # RUN:   /alternatename:_mainCRTStartup=_bar -- %t.obj
 # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=MAINADDR %s
 
-MAINADDR: AddressOfEntryPoint: 0x100C
+MAINADDR: AddressOfEntryPoint: 0x1004
 
 # RUN: lld -flavor link /out:%t.exe /subsystem:console /entry:baz -- %t.obj
 # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=MANGLE %s





More information about the llvm-commits mailing list