[lld-macho] Fold cfstrings with --deduplicate-literals

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
This commit is contained in:
Keith Smiley 2022-07-19 17:03:34 -07:00
parent a73a84c447
commit 15f685eaa8
No known key found for this signature in database
GPG Key ID: 33BA60D44C7167F8
5 changed files with 26 additions and 17 deletions

View 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::none) {
if (config->icfLevel == ICFLevel::safe) if (config->icfLevel == ICFLevel::safe)
markAddrSigSymbols(); markAddrSigSymbols();
foldIdenticalSections(); foldIdenticalSections(/*onlyCfStrings=*/false);
} else if (config->dedupLiterals) {
foldIdenticalSections(/*onlyCfStrings=*/true);
} }
// Write to an output file. // Write to an output file.

View File

@ -395,7 +395,7 @@ void macho::markAddrSigSymbols() {
} }
} }
void macho::foldIdenticalSections() { void macho::foldIdenticalSections(bool onlyCfStrings) {
TimeTraceScope timeScope("Fold Identical Code Sections"); TimeTraceScope timeScope("Fold Identical Code Sections");
// The ICF equivalence-class segregation algorithm relies on pre-computed // The ICF equivalence-class segregation algorithm relies on pre-computed
// hashes of InputSection::data for the ConcatOutputSection::inputs and all // hashes of InputSection::data for the ConcatOutputSection::inputs and all
@ -416,6 +416,7 @@ void macho::foldIdenticalSections() {
for (ConcatInputSection *isec : inputSections) { for (ConcatInputSection *isec : inputSections) {
// FIXME: consider non-code __text sections as hashable? // FIXME: consider non-code __text sections as hashable?
bool isHashable = bool isHashable =
(!onlyCfStrings || isCfStringSection(isec)) &&
(isCodeSection(isec) || isCfStringSection(isec) || (isCodeSection(isec) || isCfStringSection(isec) ||
isClassRefsSection(isec) || isGccExceptTabSection(isec)) && isClassRefsSection(isec) || isGccExceptTabSection(isec)) &&
!isec->keepUnique && !isec->shouldOmitFromOutput() && !isec->keepUnique && !isec->shouldOmitFromOutput() &&

View File

@ -19,7 +19,7 @@ class Symbol;
void markAddrSigSymbols(); void markAddrSigSymbols();
void markSymAsAddrSig(Symbol *s); void markSymAsAddrSig(Symbol *s);
void foldIdenticalSections(); void foldIdenticalSections(bool onlyCfStrings);
} // namespace macho } // namespace macho
} // namespace lld } // namespace lld

View File

@ -263,11 +263,15 @@ static Optional<size_t> getRecordSize(StringRef segname, StringRef name) {
if (segname == segment_names::ld) if (segname == segment_names::ld)
return target->wordSize == 8 ? 32 : 20; return target->wordSize == 8 ? 32 : 20;
} }
if (config->icfLevel == ICFLevel::none) if (!config->dedupLiterals)
return {}; return {};
if (name == section_names::cfString && segname == segment_names::data) if (name == section_names::cfString && segname == segment_names::data)
return target->wordSize == 8 ? 32 : 16; return target->wordSize == 8 ? 32 : 16;
if (config->icfLevel == ICFLevel::none)
return {};
if (name == section_names::objcClassRefs && segname == segment_names::data) if (name == section_names::objcClassRefs && segname == segment_names::data)
return target->wordSize; return target->wordSize;
return {}; return {};

View 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/foo1.s -o %t/foo1.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo2.s -o %t/foo2.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: %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: (__TEXT,__text) section
# CHECK-NEXT: _foo1: # CHECK-NEXT: _foo1:
@ -22,18 +24,18 @@
# CHECK-DAG: [[#FOO]] g F __TEXT,__text _foo2 # CHECK-DAG: [[#FOO]] g F __TEXT,__text _foo2
## Make sure we don't emit redundant bind / rebase opcodes for folded sections. ## Make sure we don't emit redundant bind / rebase opcodes for folded sections.
# CHECK: Rebase table: # LITERALS: Rebase table:
# CHECK-NEXT: segment section address type # LITERALS-NEXT: segment section address type
# CHECK-NEXT: __DATA_CONST __cfstring {{.*}} pointer # LITERALS-NEXT: __DATA_CONST __cfstring {{.*}} pointer
# CHECK-NEXT: __DATA_CONST __cfstring {{.*}} pointer # LITERALS-NEXT: __DATA_CONST __cfstring {{.*}} pointer
# CHECK-NEXT: __DATA_CONST __cfstring {{.*}} pointer # LITERALS-NEXT: __DATA_CONST __cfstring {{.*}} pointer
# CHECK-EMPTY: # LITERALS-EMPTY:
# CHECK-NEXT: Bind table: # LITERALS-NEXT: Bind table:
# CHECK-NEXT: segment section address type addend dylib symbol # LITERALS-NEXT: segment section address type addend dylib symbol
# CHECK-NEXT: __DATA_CONST __cfstring {{.*}} pointer 0 CoreFoundation ___CFConstantStringClassReference # LITERALS-NEXT: __DATA_CONST __cfstring {{.*}} pointer 0 CoreFoundation ___CFConstantStringClassReference
# CHECK-NEXT: __DATA_CONST __cfstring {{.*}} pointer 0 CoreFoundation ___CFConstantStringClassReference # LITERALS-NEXT: __DATA_CONST __cfstring {{.*}} pointer 0 CoreFoundation ___CFConstantStringClassReference
# CHECK-NEXT: __DATA_CONST __cfstring {{.*}} pointer 0 CoreFoundation ___CFConstantStringClassReference # LITERALS-NEXT: __DATA_CONST __cfstring {{.*}} pointer 0 CoreFoundation ___CFConstantStringClassReference
# CHECK-EMPTY: # LITERALS-EMPTY:
#--- foo1.s #--- foo1.s
.cstring .cstring