[lld] r340555 - COFF: Implement safe ICF on rodata using address-significance tables.

Peter Collingbourne via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 23 10:44:42 PDT 2018


Author: pcc
Date: Thu Aug 23 10:44:42 2018
New Revision: 340555

URL: http://llvm.org/viewvc/llvm-project?rev=340555&view=rev
Log:
COFF: Implement safe ICF on rodata using address-significance tables.

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

Added:
    lld/trunk/test/COFF/Inputs/icf-safe.s
    lld/trunk/test/COFF/icf-safe.s
Modified:
    lld/trunk/COFF/Chunks.h
    lld/trunk/COFF/Driver.cpp
    lld/trunk/COFF/ICF.cpp
    lld/trunk/COFF/InputFiles.cpp
    lld/trunk/COFF/InputFiles.h

Modified: lld/trunk/COFF/Chunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.h?rev=340555&r1=340554&r2=340555&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.h (original)
+++ lld/trunk/COFF/Chunks.h Thu Aug 23 10:44:42 2018
@@ -114,6 +114,10 @@ protected:
 public:
   // The offset from beginning of the output section. The writer sets a value.
   uint64_t OutputSectionOff = 0;
+
+  // Whether this section needs to be kept distinct from other sections during
+  // ICF. This is set by the driver using address-significance tables.
+  bool KeepUnique = false;
 };
 
 // A chunk corresponding a section of an input file.

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=340555&r1=340554&r2=340555&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Thu Aug 23 10:44:42 2018
@@ -32,6 +32,7 @@
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/LEB128.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Process.h"
 #include "llvm/Support/TarWriter.h"
@@ -741,6 +742,46 @@ static void parseOrderFile(StringRef Arg
   }
 }
 
+static void markAddrsig(Symbol *S) {
+  if (auto *D = dyn_cast_or_null<Defined>(S))
+    if (Chunk *C = D->getChunk())
+      C->KeepUnique = true;
+}
+
+static void findKeepUniqueSections() {
+  // Exported symbols could be address-significant in other executables or DSOs,
+  // so we conservatively mark them as address-significant.
+  for (Export &R : Config->Exports)
+    markAddrsig(R.Sym);
+
+  // Visit the address-significance table in each object file and mark each
+  // referenced symbol as address-significant.
+  for (ObjFile *Obj : ObjFile::Instances) {
+    ArrayRef<Symbol *> Syms = Obj->getSymbols();
+    if (Obj->AddrsigSec) {
+      ArrayRef<uint8_t> Contents;
+      Obj->getCOFFObj()->getSectionContents(Obj->AddrsigSec, Contents);
+      const uint8_t *Cur = Contents.begin();
+      while (Cur != Contents.end()) {
+        unsigned Size;
+        const char *Err;
+        uint64_t SymIndex = decodeULEB128(Cur, &Size, Contents.end(), &Err);
+        if (Err)
+          fatal(toString(Obj) + ": could not decode addrsig section: " + Err);
+        if (SymIndex >= Syms.size())
+          fatal(toString(Obj) + ": invalid symbol index in addrsig section");
+        markAddrsig(Syms[SymIndex]);
+        Cur += Size;
+      }
+    } else {
+      // If an object file does not have an address-significance table,
+      // conservatively mark all of its symbols as address-significant.
+      for (Symbol *S : Syms)
+        markAddrsig(S);
+    }
+  }
+}
+
 void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
   // If the first command line argument is "/lib", link.exe acts like lib.exe.
   // We call our own implementation of lib.exe that understands bitcode files.
@@ -1452,8 +1493,10 @@ void LinkerDriver::link(ArrayRef<const c
     markLive(Symtab->getChunks());
 
   // Identify identical COMDAT sections to merge them.
-  if (Config->DoICF)
+  if (Config->DoICF) {
+    findKeepUniqueSections();
     doICF(Symtab->getChunks());
+  }
 
   // Write the result.
   writeResult();

Modified: lld/trunk/COFF/ICF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/ICF.cpp?rev=340555&r1=340554&r2=340555&view=diff
==============================================================================
--- lld/trunk/COFF/ICF.cpp (original)
+++ lld/trunk/COFF/ICF.cpp Thu Aug 23 10:44:42 2018
@@ -93,7 +93,11 @@ bool ICF::isEligible(SectionChunk *C) {
     return true;
 
   // So are vtables.
-  return C->Sym && C->Sym->getName().startswith("??_7");
+  if (C->Sym && C->Sym->getName().startswith("??_7"))
+    return true;
+
+  // Anything else not in an address-significance table is eligible.
+  return !C->KeepUnique;
 }
 
 // Split an equivalence class into smaller classes.

Modified: lld/trunk/COFF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.cpp?rev=340555&r1=340554&r2=340555&view=diff
==============================================================================
--- lld/trunk/COFF/InputFiles.cpp (original)
+++ lld/trunk/COFF/InputFiles.cpp Thu Aug 23 10:44:42 2018
@@ -161,6 +161,11 @@ SectionChunk *ObjFile::readSection(uint3
     return nullptr;
   }
 
+  if (Name == ".llvm_addrsig") {
+    AddrsigSec = Sec;
+    return nullptr;
+  }
+
   // Object files may have DWARF debug info or MS CodeView debug info
   // (or both).
   //

Modified: lld/trunk/COFF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.h?rev=340555&r1=340554&r2=340555&view=diff
==============================================================================
--- lld/trunk/COFF/InputFiles.h (original)
+++ lld/trunk/COFF/InputFiles.h Thu Aug 23 10:44:42 2018
@@ -145,6 +145,8 @@ public:
   // if we are not producing a PDB.
   llvm::pdb::DbiModuleDescriptorBuilder *ModuleDBI = nullptr;
 
+  const coff_section *AddrsigSec = nullptr;
+
 private:
   void initializeChunks();
   void initializeSymbols();

Added: lld/trunk/test/COFF/Inputs/icf-safe.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/Inputs/icf-safe.s?rev=340555&view=auto
==============================================================================
--- lld/trunk/test/COFF/Inputs/icf-safe.s (added)
+++ lld/trunk/test/COFF/Inputs/icf-safe.s Thu Aug 23 10:44:42 2018
@@ -0,0 +1,9 @@
+.section .rdata,"dr",one_only,non_addrsig1
+.globl non_addrsig1
+non_addrsig1:
+.byte 3
+
+.section .rdata,"dr",one_only,non_addrsig2
+.globl non_addrsig2
+non_addrsig2:
+.byte 3

Added: lld/trunk/test/COFF/icf-safe.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/icf-safe.s?rev=340555&view=auto
==============================================================================
--- lld/trunk/test/COFF/icf-safe.s (added)
+++ lld/trunk/test/COFF/icf-safe.s Thu Aug 23 10:44:42 2018
@@ -0,0 +1,36 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-win32 %s -o %t1.obj
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-win32 %S/Inputs/icf-safe.s -o %t2.obj
+# RUN: lld-link /dll /noentry /out:%t.dll /verbose /opt:noref,icf %t1.obj %t2.obj 2>&1 | FileCheck %s
+# RUN: lld-link /dll /noentry /out:%t.dll /verbose /opt:noref,icf /export:g3 /export:g4 %t1.obj %t2.obj 2>&1 | FileCheck --check-prefix=EXPORT %s
+
+# CHECK-NOT: Selected
+# CHECK: Selected g3
+# CHECK-NEXT:   Removed g4
+# CHECK-NOT: Removed
+# CHECK-NOT: Selected
+
+# EXPORT-NOT: Selected
+
+.section .rdata,"dr",one_only,g1
+.globl g1
+g1:
+.byte 1
+
+.section .rdata,"dr",one_only,g2
+.globl g2
+g2:
+.byte 1
+
+.section .rdata,"dr",one_only,g3
+.globl g3
+g3:
+.byte 2
+
+.section .rdata,"dr",one_only,g4
+.globl g4
+g4:
+.byte 2
+
+.addrsig
+.addrsig_sym g1
+.addrsig_sym g2




More information about the llvm-commits mailing list