[lld-macho] Fold cfstrings with --deduplicate-literals
authorKeith Smiley <keithbsmiley@gmail.com>
Wed, 20 Jul 2022 00:03:34 +0000 (17:03 -0700)
committerKeith Smiley <keithbsmiley@gmail.com>
Wed, 20 Jul 2022 18:11:09 +0000 (11:11 -0700)
Similar to cstrings ld64 always deduplicates cfstrings. This was already
being done when enabling ICF, but for debug builds you may want to flip
this on if you cannot eliminate your instances of this, so this change
makes --deduplicate-literals also apply to cfstrings.

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

lld/MachO/Driver.cpp
lld/MachO/ICF.cpp
lld/MachO/ICF.h
lld/MachO/InputFiles.cpp
lld/test/MachO/cfstring-dedup.s

index f5c4e82..8be29eb 100644 (file)
@@ -1666,7 +1666,9 @@ bool macho::link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
     if (config->icfLevel != ICFLevel::none) {
       if (config->icfLevel == ICFLevel::safe)
         markAddrSigSymbols();
-      foldIdenticalSections();
+      foldIdenticalSections(/*onlyCfStrings=*/false);
+    } else if (config->dedupLiterals) {
+      foldIdenticalSections(/*onlyCfStrings=*/true);
     }
 
     // Write to an output file.
index 34ffd05..d06fbc6 100644 (file)
@@ -395,7 +395,7 @@ void macho::markAddrSigSymbols() {
   }
 }
 
-void macho::foldIdenticalSections() {
+void macho::foldIdenticalSections(bool onlyCfStrings) {
   TimeTraceScope timeScope("Fold Identical Code Sections");
   // The ICF equivalence-class segregation algorithm relies on pre-computed
   // hashes of InputSection::data for the ConcatOutputSection::inputs and all
@@ -416,6 +416,7 @@ void macho::foldIdenticalSections() {
   for (ConcatInputSection *isec : inputSections) {
     // FIXME: consider non-code __text sections as hashable?
     bool isHashable =
+        (!onlyCfStrings || isCfStringSection(isec)) &&
         (isCodeSection(isec) || isCfStringSection(isec) ||
          isClassRefsSection(isec) || isGccExceptTabSection(isec)) &&
         !isec->keepUnique && !isec->shouldOmitFromOutput() &&
index a287692..b7e695d 100644 (file)
@@ -19,7 +19,7 @@ class Symbol;
 
 void markAddrSigSymbols();
 void markSymAsAddrSig(Symbol *s);
-void foldIdenticalSections();
+void foldIdenticalSections(bool onlyCfStrings);
 
 } // namespace macho
 } // namespace lld
index 1abbc30..93cde5f 100644 (file)
@@ -263,11 +263,15 @@ static Optional<size_t> getRecordSize(StringRef segname, StringRef name) {
     if (segname == segment_names::ld)
       return target->wordSize == 8 ? 32 : 20;
   }
-  if (config->icfLevel == ICFLevel::none)
+  if (!config->dedupLiterals)
     return {};
 
   if (name == section_names::cfString && segname == segment_names::data)
     return target->wordSize == 8 ? 32 : 16;
+
+  if (config->icfLevel == ICFLevel::none)
+    return {};
+
   if (name == section_names::objcClassRefs && segname == segment_names::data)
     return target->wordSize;
   return {};
index 73aa50f..6457c18 100644 (file)
@@ -3,7 +3,9 @@
 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo1.s -o %t/foo1.o
 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo2.s -o %t/foo2.o
 # RUN: %lld -dylib --icf=all -framework CoreFoundation %t/foo1.o %t/foo2.o -o %t/foo
-# RUN: llvm-objdump --macho --rebase --bind --syms -d %t/foo | FileCheck %s
+# RUN: llvm-objdump --macho --rebase --bind --syms -d %t/foo | FileCheck %s --check-prefixes=CHECK,LITERALS
+# RUN: %lld -dylib --deduplicate-literals -framework CoreFoundation %t/foo1.o %t/foo2.o -o %t/foo
+# RUN: llvm-objdump --macho --rebase --bind --syms -d %t/foo | FileCheck %s --check-prefix=LITERALS
 
 # CHECK:       (__TEXT,__text) section
 # CHECK-NEXT:  _foo1:
 # CHECK-DAG:   [[#FOO]]        g     F __TEXT,__text _foo2
 
 ## Make sure we don't emit redundant bind / rebase opcodes for folded sections.
-# CHECK:       Rebase table:
-# CHECK-NEXT:  segment  section          address  type
-# CHECK-NEXT:  __DATA_CONST __cfstring   {{.*}}   pointer
-# CHECK-NEXT:  __DATA_CONST __cfstring   {{.*}}   pointer
-# CHECK-NEXT:  __DATA_CONST __cfstring   {{.*}}   pointer
-# CHECK-EMPTY:
-# CHECK-NEXT:  Bind table:
-# CHECK-NEXT:  segment      section      address  type       addend dylib            symbol
-# CHECK-NEXT:  __DATA_CONST __cfstring   {{.*}}   pointer         0 CoreFoundation   ___CFConstantStringClassReference
-# CHECK-NEXT:  __DATA_CONST __cfstring   {{.*}}   pointer         0 CoreFoundation   ___CFConstantStringClassReference
-# CHECK-NEXT:  __DATA_CONST __cfstring   {{.*}}   pointer         0 CoreFoundation   ___CFConstantStringClassReference
-# CHECK-EMPTY:
+# LITERALS:       Rebase table:
+# LITERALS-NEXT:  segment  section          address  type
+# LITERALS-NEXT:  __DATA_CONST __cfstring   {{.*}}   pointer
+# LITERALS-NEXT:  __DATA_CONST __cfstring   {{.*}}   pointer
+# LITERALS-NEXT:  __DATA_CONST __cfstring   {{.*}}   pointer
+# LITERALS-EMPTY:
+# LITERALS-NEXT:  Bind table:
+# LITERALS-NEXT:  segment      section      address  type       addend dylib            symbol
+# LITERALS-NEXT:  __DATA_CONST __cfstring   {{.*}}   pointer         0 CoreFoundation   ___CFConstantStringClassReference
+# LITERALS-NEXT:  __DATA_CONST __cfstring   {{.*}}   pointer         0 CoreFoundation   ___CFConstantStringClassReference
+# LITERALS-NEXT:  __DATA_CONST __cfstring   {{.*}}   pointer         0 CoreFoundation   ___CFConstantStringClassReference
+# LITERALS-EMPTY:
 
 #--- foo1.s
 .cstring