[lld] r341175 - [COFF] When doing automatic dll imports, replace whole .refptr.<var> chunks with __imp_<var>

Martin Storsjo via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 31 00:45:20 PDT 2018


Author: mstorsjo
Date: Fri Aug 31 00:45:20 2018
New Revision: 341175

URL: http://llvm.org/viewvc/llvm-project?rev=341175&view=rev
Log:
[COFF] When doing automatic dll imports, replace whole .refptr.<var> chunks with __imp_<var>

After fixing up the runtime pseudo relocation, the .refptr.<var>
will be a plain pointer with the same value as the IAT entry itself.
To save a little binary size and reduce the number of runtime pseudo
relocations, redirect references to the IAT entry (via the __imp_<var>
symbol) itself and discard the .refptr.<var> chunk (as long as the
same section chunk doesn't contain anything else than the single
pointer).

As there are now cases for both setting the Live variable to true
and false externally, remove the accessors and setters and just make
the variable public instead.

Differential Revision: https://reviews.llvm.org/D51456

Added:
    lld/trunk/test/COFF/autoimport-refptr.s
Modified:
    lld/trunk/COFF/Chunks.cpp
    lld/trunk/COFF/Chunks.h
    lld/trunk/COFF/ICF.cpp
    lld/trunk/COFF/MarkLive.cpp
    lld/trunk/COFF/PDB.cpp
    lld/trunk/COFF/SymbolTable.cpp
    lld/trunk/COFF/Symbols.cpp
    lld/trunk/COFF/Writer.cpp

Modified: lld/trunk/COFF/Chunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.cpp?rev=341175&r1=341174&r2=341175&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.cpp (original)
+++ lld/trunk/COFF/Chunks.cpp Fri Aug 31 00:45:20 2018
@@ -758,12 +758,12 @@ void MergeChunk::addSection(SectionChunk
 
 void MergeChunk::finalizeContents() {
   for (SectionChunk *C : Sections)
-    if (C->isLive())
+    if (C->Live)
       Builder.add(toStringRef(C->getContents()));
   Builder.finalize();
 
   for (SectionChunk *C : Sections) {
-    if (!C->isLive())
+    if (!C->Live)
       continue;
     size_t Off = Builder.getOffset(toStringRef(C->getContents()));
     C->setOutputSection(Out);

Modified: lld/trunk/COFF/Chunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.h?rev=341175&r1=341174&r2=341175&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.h (original)
+++ lld/trunk/COFF/Chunks.h Fri Aug 31 00:45:20 2018
@@ -174,16 +174,6 @@ public:
 
   StringRef getDebugName() override;
 
-  // Returns true if the chunk was not dropped by GC.
-  bool isLive() { return Live; }
-
-  // Used by the garbage collector.
-  void markLive() {
-    assert(Config->DoGC && "should only mark things live from GC");
-    assert(!isLive() && "Cannot mark an already live section!");
-    Live = true;
-  }
-
   // True if this is a codeview debug info chunk. These will not be laid out in
   // the image. Instead they will end up in the PDB, if one is requested.
   bool isCodeView() const {
@@ -224,13 +214,13 @@ public:
 
   ArrayRef<coff_relocation> Relocs;
 
+  // Used by the garbage collector.
+  bool Live;
+
 private:
   StringRef SectionName;
   std::vector<SectionChunk *> AssocChildren;
 
-  // Used by the garbage collector.
-  bool Live;
-
   // Used for ICF (Identical COMDAT Folding)
   void replace(SectionChunk *Other);
   uint32_t Class[2] = {0, 0};

Modified: lld/trunk/COFF/ICF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/ICF.cpp?rev=341175&r1=341174&r2=341175&view=diff
==============================================================================
--- lld/trunk/COFF/ICF.cpp (original)
+++ lld/trunk/COFF/ICF.cpp Fri Aug 31 00:45:20 2018
@@ -80,7 +80,7 @@ private:
 bool ICF::isEligible(SectionChunk *C) {
   // Non-comdat chunks, dead chunks, and writable chunks are not elegible.
   bool Writable = C->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_WRITE;
-  if (!C->isCOMDAT() || !C->isLive() || Writable)
+  if (!C->isCOMDAT() || !C->Live || Writable)
     return false;
 
   // Code sections are eligible.

Modified: lld/trunk/COFF/MarkLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/MarkLive.cpp?rev=341175&r1=341174&r2=341175&view=diff
==============================================================================
--- lld/trunk/COFF/MarkLive.cpp (original)
+++ lld/trunk/COFF/MarkLive.cpp Fri Aug 31 00:45:20 2018
@@ -32,13 +32,13 @@ void markLive(ArrayRef<Chunk *> Chunks)
   // COMDAT section chunks are dead by default. Add non-COMDAT chunks.
   for (Chunk *C : Chunks)
     if (auto *SC = dyn_cast<SectionChunk>(C))
-      if (SC->isLive())
+      if (SC->Live)
         Worklist.push_back(SC);
 
   auto Enqueue = [&](SectionChunk *C) {
-    if (C->isLive())
+    if (C->Live)
       return;
-    C->markLive();
+    C->Live = true;
     Worklist.push_back(C);
   };
 
@@ -57,7 +57,7 @@ void markLive(ArrayRef<Chunk *> Chunks)
 
   while (!Worklist.empty()) {
     SectionChunk *SC = Worklist.pop_back_val();
-    assert(SC->isLive() && "We mark as live when pushing onto the worklist!");
+    assert(SC->Live && "We mark as live when pushing onto the worklist!");
 
     // Mark all symbols listed in the relocation table for this section.
     for (Symbol *B : SC->symbols())

Modified: lld/trunk/COFF/PDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/PDB.cpp?rev=341175&r1=341174&r2=341175&view=diff
==============================================================================
--- lld/trunk/COFF/PDB.cpp (original)
+++ lld/trunk/COFF/PDB.cpp Fri Aug 31 00:45:20 2018
@@ -821,7 +821,7 @@ void PDBLinker::addObjFile(ObjFile *File
   uint32_t Modi = File->ModuleDBI->getModuleIndex();
   for (Chunk *C : Chunks) {
     auto *SecChunk = dyn_cast<SectionChunk>(C);
-    if (!SecChunk || !SecChunk->isLive())
+    if (!SecChunk || !SecChunk->Live)
       continue;
     pdb::SectionContrib SC = createSectionContrib(SecChunk, Modi);
     File->ModuleDBI->setFirstSectionContrib(SC);
@@ -851,7 +851,7 @@ void PDBLinker::addObjFile(ObjFile *File
   DebugChecksumsSubsectionRef Checksums;
   std::vector<ulittle32_t *> StringTableReferences;
   for (SectionChunk *DebugChunk : File->getDebugChunks()) {
-    if (!DebugChunk->isLive() || DebugChunk->getSectionName() != ".debug$S")
+    if (!DebugChunk->Live || DebugChunk->getSectionName() != ".debug$S")
       continue;
 
     ArrayRef<uint8_t> RelocatedDebugContents =

Modified: lld/trunk/COFF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/SymbolTable.cpp?rev=341175&r1=341174&r2=341175&view=diff
==============================================================================
--- lld/trunk/COFF/SymbolTable.cpp (original)
+++ lld/trunk/COFF/SymbolTable.cpp Fri Aug 31 00:45:20 2018
@@ -169,6 +169,23 @@ bool SymbolTable::handleMinGWAutomaticIm
   // reference itself to point at the IAT entry.
   Sym->replaceKeepingName(Imp, sizeof(DefinedImportData));
   cast<DefinedImportData>(Sym)->IsRuntimePseudoReloc = true;
+
+  // There may exist symbols named .refptr.<name> which only consist
+  // of a single pointer to <name>. If it turns out <name> is
+  // automatically imported, we don't need to keep the .refptr.<name>
+  // pointer at all, but redirect all accesses to it to the IAT entry
+  // for __imp_<name> instead, and drop the whole .refptr.<name> chunk.
+  DefinedRegular *Refptr =
+      dyn_cast_or_null<DefinedRegular>(find((".refptr." + Name).str()));
+  size_t PtrSize = Config->is64() ? 8 : 4;
+  if (Refptr && Refptr->getChunk()->getSize() == PtrSize) {
+    SectionChunk *SC = dyn_cast_or_null<SectionChunk>(Refptr->getChunk());
+    if (SC && SC->Relocs.size() == 1 && *SC->symbols().begin() == Sym) {
+        log("Replacing .refptr." + Name + " with " + Imp->getName());
+        Refptr->getChunk()->Live = false;
+        Refptr->replaceKeepingName(Imp, sizeof(DefinedImportData));
+    }
+  }
   return true;
 }
 

Modified: lld/trunk/COFF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Symbols.cpp?rev=341175&r1=341174&r2=341175&view=diff
==============================================================================
--- lld/trunk/COFF/Symbols.cpp (original)
+++ lld/trunk/COFF/Symbols.cpp Fri Aug 31 00:45:20 2018
@@ -54,7 +54,7 @@ InputFile *Symbol::getFile() {
 
 bool Symbol::isLive() const {
   if (auto *R = dyn_cast<DefinedRegular>(this))
-    return R->getChunk()->isLive();
+    return R->getChunk()->Live;
   if (auto *Imp = dyn_cast<DefinedImportData>(this))
     return Imp->File->Live;
   if (auto *Imp = dyn_cast<DefinedImportThunk>(this))

Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=341175&r1=341174&r2=341175&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Fri Aug 31 00:45:20 2018
@@ -435,7 +435,7 @@ void Writer::createSections() {
   std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> Map;
   for (Chunk *C : Symtab->getChunks()) {
     auto *SC = dyn_cast<SectionChunk>(C);
-    if (SC && !SC->isLive()) {
+    if (SC && !SC->Live) {
       if (Config->Verbose)
         SC->printDiscardedMessage();
       continue;
@@ -1014,7 +1014,7 @@ static void markSymbolsWithRelocations(O
     // We only care about live section chunks. Common chunks and other chunks
     // don't generally contain relocations.
     SectionChunk *SC = dyn_cast<SectionChunk>(C);
-    if (!SC || !SC->isLive())
+    if (!SC || !SC->Live)
       continue;
 
     for (const coff_relocation &Reloc : SC->Relocs) {
@@ -1097,7 +1097,7 @@ void Writer::markSymbolsForRVATable(ObjF
     // is associated with something like a vtable and the vtable is discarded.
     // In this case, the associated gfids section is discarded, and we don't
     // mark the virtual member functions as address-taken by the vtable.
-    if (!C->isLive())
+    if (!C->Live)
       continue;
 
     // Validate that the contents look like symbol table indices.
@@ -1153,7 +1153,7 @@ void Writer::createRuntimePseudoRelocs()
 
   for (Chunk *C : Symtab->getChunks()) {
     auto *SC = dyn_cast<SectionChunk>(C);
-    if (!SC || !SC->isLive())
+    if (!SC || !SC->Live)
       continue;
     SC->getRuntimePseudoRelocs(Rels);
   }

Added: lld/trunk/test/COFF/autoimport-refptr.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/autoimport-refptr.s?rev=341175&view=auto
==============================================================================
--- lld/trunk/test/COFF/autoimport-refptr.s (added)
+++ lld/trunk/test/COFF/autoimport-refptr.s Fri Aug 31 00:45:20 2018
@@ -0,0 +1,65 @@
+# REQUIRES: x86
+
+# RUN: echo -e ".global variable\n.global DllMainCRTStartup\n.text\nDllMainCRTStartup:\nret\n.data\nvariable:\n.long 42" > %t-lib.s
+# RUN: llvm-mc -triple=x86_64-windows-gnu %t-lib.s -filetype=obj -o %t-lib.obj
+# RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib
+
+# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj
+# RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose
+
+# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s
+# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s
+# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=CONTENTS %s
+
+# IMPORTS: Import {
+# IMPORTS-NEXT: Name: autoimport-refptr.s.tmp-lib.dll
+# IMPORTS-NEXT: ImportLookupTableRVA: 0x2030
+# IMPORTS-NEXT: ImportAddressTableRVA: 0x2040
+# IMPORTS-NEXT: Symbol: variable (0)
+# IMPORTS-NEXT: }
+
+# DISASM: Disassembly of section .text:
+# DISASM: .text:
+# Relative offset at 0x1002 pointing at the IAT at 0x2040
+# DISASM: 140001000:      48 8b 05 39 10 00 00    movq    4153(%rip), %rax
+# DISASM: 140001007:      8b 00   movl    (%rax), %eax
+# Relative offset at 0x100b pointing at the .refptr.localvar stub at
+# 0x2000
+# DISASM: 140001009:      48 8b 0d f0 0f 00 00    movq    4080(%rip), %rcx
+# DISASM: 140001010:      03 01   addl    (%rcx), %eax
+# DISASM: 140001012:      c3      retq
+
+# relocs: pointing at an empty list of runtime pseudo relocs.
+# localvar: 42
+# CONTENTS: Contents of section .data:
+# CONTENTS:  140003000 08200040 01000000 08200040 01000000
+# CONTENTS:  140003010 2a000000
+
+    .global main
+    .global localvar
+    .text
+main:
+    movq .refptr.variable(%rip), %rax
+    movl (%rax), %eax
+    movq .refptr.localvar(%rip), %rcx
+    addl (%rcx), %eax
+    ret
+
+    .data
+relocs:
+    .quad __RUNTIME_PSEUDO_RELOC_LIST__
+    .quad __RUNTIME_PSEUDO_RELOC_LIST_END__
+localvar:
+    .int 42
+
+# Normally the compiler wouldn't emit a stub for a variable that is
+# emitted in the same translation unit.
+    .section .rdata$.refptr.localvar,"dr",discard,.refptr.localvar
+    .global .refptr.localvar
+.refptr.localvar:
+    .quad localvar
+
+    .section .rdata$.refptr.variable,"dr",discard,.refptr.variable
+    .global .refptr.variable
+.refptr.variable:
+    .quad variable




More information about the llvm-commits mailing list