bool emitChainedFixups = false;
bool timeTraceEnabled = false;
bool dataConst = false;
- bool dedupLiterals = true;
+ bool dedupStrings = true;
bool deadStripDuplicates = false;
bool omitDebugInfo = false;
bool warnDylibInstallName = false;
// Either way, we must unconditionally finalize it here.
in.cStringSection->finalizeContents();
in.objcMethnameSection->finalizeContents();
- if (in.wordLiteralSection)
- in.wordLiteralSection->finalizeContents();
+ in.wordLiteralSection->finalizeContents();
}
static void addSynthenticMethnames() {
config->emitInitOffsets =
config->emitChainedFixups || args.hasArg(OPT_init_offsets);
config->icfLevel = getICFLevel(args);
- config->dedupLiterals =
- args.hasFlag(OPT_deduplicate_literals, OPT_icf_eq, false) ||
- config->icfLevel != ICFLevel::none;
+ config->dedupStrings =
+ args.hasFlag(OPT_deduplicate_strings, OPT_no_deduplicate_strings, true);
config->deadStripDuplicates = args.hasArg(OPT_dead_strip_duplicates);
config->warnDylibInstallName = args.hasFlag(
OPT_warn_dylib_install_name, OPT_no_warn_dylib_install_name, false);
if (config->icfLevel == ICFLevel::safe)
markAddrSigSymbols();
foldIdenticalSections(/*onlyCfStrings=*/false);
- } else if (config->dedupLiterals) {
+ } else if (config->dedupStrings) {
foldIdenticalSections(/*onlyCfStrings=*/true);
}
if (segname == segment_names::ld)
return target->wordSize == 8 ? 32 : 20;
}
- if (!config->dedupLiterals)
+ if (!config->dedupStrings)
return {};
if (name == section_names::cfString && segname == segment_names::data)
section.doneSplitting = true;
};
- if (sectionType(sec.flags) == S_CSTRING_LITERALS ||
- (config->dedupLiterals && isWordLiteralSection(sec.flags))) {
- if (sec.nreloc && config->dedupLiterals)
+ if (sectionType(sec.flags) == S_CSTRING_LITERALS) {
+ if (sec.nreloc && config->dedupStrings)
fatal(toString(this) + " contains relocations in " + sec.segname + "," +
sec.sectname +
- ", so LLD cannot deduplicate literals. Try re-running without "
- "--deduplicate-literals.");
-
- InputSection *isec;
- if (sectionType(sec.flags) == S_CSTRING_LITERALS) {
- isec = make<CStringInputSection>(section, data, align,
- /*dedupLiterals=*/name ==
- section_names::objcMethname ||
- config->dedupLiterals);
- // FIXME: parallelize this?
- cast<CStringInputSection>(isec)->splitIntoPieces();
- } else {
- isec = make<WordLiteralInputSection>(section, data, align);
- }
+ ", so LLD cannot deduplicate strings. Try re-running with "
+ "--no-deduplicate-strings.");
+
+ InputSection *isec = make<CStringInputSection>(
+ section, data, align,
+ /*dedupLiterals=*/name == section_names::objcMethname ||
+ config->dedupStrings);
+ // FIXME: parallelize this?
+ cast<CStringInputSection>(isec)->splitIntoPieces();
+ section.subsections.push_back({0, isec});
+ } else if (isWordLiteralSection(sec.flags)) {
+ if (sec.nreloc)
+ fatal(toString(this) + " contains unsupported relocations in " +
+ sec.segname + "," + sec.sectname);
+ InputSection *isec = make<WordLiteralInputSection>(section, data, align);
section.subsections.push_back({0, isec});
} else if (auto recordSize = getRecordSize(segname, name)) {
splitRecords(*recordSize);
def time_trace_granularity_eq: Joined<["--"], "time-trace-granularity=">,
HelpText<"Minimum time granularity (in microseconds) traced by time profiler">,
Group<grp_lld>;
-def deduplicate_literals: Flag<["--"], "deduplicate-literals">,
- HelpText<"Enable literal deduplication. This is implied by --icf={safe,all}">,
+def deduplicate_strings: Flag<["--"], "deduplicate-strings">,
+ HelpText<"Enable string deduplication">,
+ Group<grp_lld>;
+def no_deduplicate_strings: Flag<["--"], "no-deduplicate-strings">,
+ HelpText<"Disable string deduplication. This helps uncover cases of comparing string addresses instead of equality and might have a link time performance benefit.">,
Group<grp_lld>;
def dead_strip_duplicates: Flag<["--"], "dead-strip-duplicates">,
HelpText<"Do not error on duplicate symbols that will be dead stripped.">,
void macho::createSyntheticSections() {
in.header = make<MachHeaderSection>();
- if (config->dedupLiterals)
+ if (config->dedupStrings)
in.cStringSection =
make<DeduplicatedCStringSection>(section_names::cString);
else
in.cStringSection = make<CStringSection>(section_names::cString);
in.objcMethnameSection =
make<DeduplicatedCStringSection>(section_names::objcMethname);
- in.wordLiteralSection =
- config->dedupLiterals ? make<WordLiteralSection>() : nullptr;
+ in.wordLiteralSection = make<WordLiteralSection>();
if (config->emitChainedFixups) {
in.chainedFixups = make<ChainedFixupsSection>();
} else {
For Xcode, this can be done by adding it to "Other linker flags" in the build
settings. For Bazel, this can be done with ``--linkopt`` or with
`rules_apple_linker <https://github.com/keith/rules_apple_linker>`_.
-The user may also need to add ``-Wl,--deduplicate-literals`` in order
-to match Apple's linker behavior more closely (otherwise problems
-can occur, for instance, in unit tests).
.. seealso::
This doc lists all significant deliberate differences in behavior between ld64
and LLD-MachO.
-String Literal Deduplication
-****************************
-ld64 always deduplicates string literals. LLD only does it when the ``--icf=``
-or the ``--deduplicate-literals`` flag is passed. Omitting deduplication by
-default ensures that our link is as fast as possible. However, it may also break
-some programs which have (incorrectly) relied on string deduplication always
-occurring. In particular, programs which compare string literals via pointer
-equality must be fixed to use value equality instead.
-
Dead Stripping Duplicate Symbols
********************************
ld64 strips dead code before reporting duplicate symbols. By default, LLD does
# 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 --no-print-imm-hex --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: %lld -dylib -framework CoreFoundation %t/foo1.o %t/foo2.o -o %t/foo
# RUN: llvm-objdump --no-print-imm-hex --macho --rebase --bind --syms -d %t/foo | FileCheck %s --check-prefix=LITERALS
# CHECK: (__TEXT,__text) section
## get dedup'ed, meaning that the output strings get their offsets "naturally"
## preserved.
-# RUN: %lld -dylib %t/align-empty.o %t/align-4-0.o %t/align-16-0.o -o %t/align-4-0-16-0
+# RUN: %lld -dylib --no-deduplicate-strings %t/align-empty.o %t/align-4-0.o %t/align-16-0.o -o %t/align-4-0-16-0
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/align-4-0-16-0 | \
# RUN: FileCheck %s -D#OFF1=4 -D#OFF2=16
-# RUN: %lld -dylib %t/align-empty.o %t/align-16-0.o %t/align-4-0.o -o %t/align-16-0-4-0
+# RUN: %lld -dylib --no-deduplicate-strings %t/align-empty.o %t/align-16-0.o %t/align-4-0.o -o %t/align-16-0-4-0
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/align-16-0-4-0 | \
# RUN: FileCheck %s -D#OFF1=16 -D#OFF2=20
-# RUN: %lld -dylib %t/align-empty.o %t/align-4-2.o %t/align-16-0.o -o %t/align-4-2-16-0
+# RUN: %lld -dylib --no-deduplicate-strings %t/align-empty.o %t/align-4-2.o %t/align-16-0.o -o %t/align-4-2-16-0
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/align-4-2-16-0 | \
# RUN: FileCheck %s -D#OFF1=6 -D#OFF2=16
-# RUN: %lld -dylib %t/align-empty.o %t/align-16-0.o %t/align-4-2.o -o %t/align-16-0-4-2
+# RUN: %lld -dylib --no-deduplicate-strings %t/align-empty.o %t/align-16-0.o %t/align-4-2.o -o %t/align-16-0-4-2
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/align-16-0-4-2 | \
# RUN: FileCheck %s -D#OFF1=16 -D#OFF2=22
-# RUN: %lld -dylib %t/align-empty.o %t/align-4-0.o %t/align-16-2.o -o %t/align-4-0-16-2
+# RUN: %lld -dylib --no-deduplicate-strings %t/align-empty.o %t/align-4-0.o %t/align-16-2.o -o %t/align-4-0-16-2
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/align-4-0-16-2 | \
# RUN: FileCheck %s -D#OFF1=4 -D#OFF2=18
-# RUN: %lld -dylib %t/align-empty.o %t/align-16-2.o %t/align-4-0.o -o %t/align-16-2-4-0
+# RUN: %lld -dylib --no-deduplicate-strings %t/align-empty.o %t/align-16-2.o %t/align-4-0.o -o %t/align-16-2-4-0
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/align-16-2-4-0 | \
# RUN: FileCheck %s -D#OFF1=18 -D#OFF2=20
## The dedup cases are more interesting...
## Same offset, different alignments => pick higher alignment
-# RUN: %lld -dylib --deduplicate-literals %t/align-empty.o %t/align-4-0.o %t/align-16-0.o -o %t/dedup-4-0-16-0
+# RUN: %lld -dylib %t/align-empty.o %t/align-4-0.o %t/align-16-0.o -o %t/dedup-4-0-16-0
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/dedup-4-0-16-0 | \
# RUN: FileCheck %s --check-prefix=DEDUP -D#OFF=16
-# RUN: %lld -dylib --deduplicate-literals %t/align-empty.o %t/align-16-0.o %t/align-4-0.o -o %t/dedup-16-0-4-0
+# RUN: %lld -dylib %t/align-empty.o %t/align-16-0.o %t/align-4-0.o -o %t/dedup-16-0-4-0
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/dedup-16-0-4-0 | \
# RUN: FileCheck %s --check-prefix=DEDUP -D#OFF=16
## 16 byte alignment vs 2 byte offset => align to 16 bytes
-# RUN: %lld -dylib --deduplicate-literals %t/align-empty.o %t/align-4-2.o %t/align-16-0.o -o %t/dedup-4-2-16-0
+# RUN: %lld -dylib %t/align-empty.o %t/align-4-2.o %t/align-16-0.o -o %t/dedup-4-2-16-0
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/dedup-4-2-16-0 | \
# RUN: FileCheck %s --check-prefix=DEDUP -D#OFF=16
-# RUN: %lld -dylib --deduplicate-literals %t/align-empty.o %t/align-16-0.o %t/align-4-2.o -o %t/dedup-16-0-4-2
+# RUN: %lld -dylib %t/align-empty.o %t/align-16-0.o %t/align-4-2.o -o %t/dedup-16-0-4-2
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/dedup-16-0-4-2 | \
# RUN: FileCheck %s --check-prefix=DEDUP -D#OFF=16
## 4 byte alignment vs 2 byte offset => align to 4 bytes
-# RUN: %lld -dylib --deduplicate-literals %t/align-empty.o %t/align-4-0.o %t/align-16-2.o -o %t/dedup-4-0-16-2
+# RUN: %lld -dylib %t/align-empty.o %t/align-4-0.o %t/align-16-2.o -o %t/dedup-4-0-16-2
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/dedup-4-0-16-2 | \
# RUN: FileCheck %s --check-prefix=DEDUP -D#OFF=4
-# RUN: %lld -dylib --deduplicate-literals %t/align-empty.o %t/align-16-2.o %t/align-4-0.o -o %t/dedup-16-2-4-0
+# RUN: %lld -dylib %t/align-empty.o %t/align-16-2.o %t/align-4-0.o -o %t/dedup-16-2-4-0
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/dedup-16-2-4-0 | \
# RUN: FileCheck %s --check-prefix=DEDUP -D#OFF=4
## Both inputs are 4-byte aligned, one via offset and the other via section alignment
-# RUN: %lld -dylib --deduplicate-literals %t/align-empty.o %t/align-4-0.o %t/align-16-4.o -o %t/dedup-4-0-16-4
+# RUN: %lld -dylib %t/align-empty.o %t/align-4-0.o %t/align-16-4.o -o %t/dedup-4-0-16-4
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/dedup-4-0-16-4 | \
# RUN: FileCheck %s --check-prefix=DEDUP -D#OFF=4
-# RUN: %lld -dylib --deduplicate-literals %t/align-empty.o %t/align-16-4.o %t/align-4-0.o -o %t/dedup-16-4-4-0
+# RUN: %lld -dylib %t/align-empty.o %t/align-16-4.o %t/align-4-0.o -o %t/dedup-16-4-4-0
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/dedup-16-4-4-0 | \
# RUN: FileCheck %s --check-prefix=DEDUP -D#OFF=4
## 8-byte offset vs 4-byte section alignment => align to 8 bytes
-# RUN: %lld -dylib --deduplicate-literals %t/align-empty.o %t/align-4-0.o %t/align-16-8.o -o %t/dedup-4-0-16-8
+# RUN: %lld -dylib %t/align-empty.o %t/align-4-0.o %t/align-16-8.o -o %t/dedup-4-0-16-8
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/dedup-4-0-16-8 | \
# RUN: FileCheck %s --check-prefix=DEDUP -D#OFF=8
-# RUN: %lld -dylib --deduplicate-literals %t/align-empty.o %t/align-16-8.o %t/align-4-0.o -o %t/dedup-16-8-4-0
+# RUN: %lld -dylib %t/align-empty.o %t/align-16-8.o %t/align-4-0.o -o %t/dedup-16-8-4-0
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/dedup-16-8-4-0 | \
# RUN: FileCheck %s --check-prefix=DEDUP -D#OFF=8
# RUN: rm -rf %t; split-file %s %t
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/more-foo.s -o %t/more-foo.o
-# RUN: %lld -dylib --deduplicate-literals %t/test.o %t/more-foo.o -o %t/test
+# RUN: %lld -dylib %t/test.o %t/more-foo.o -o %t/test
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/test | \
# RUN: FileCheck %s --check-prefix=STR --implicit-check-not foo --implicit-check-not bar
# RUN: llvm-objdump --macho --section="__DATA,ptrs" --syms %t/test | FileCheck %s
# RUN: llvm-mc -g -filetype=obj -triple=x86_64-apple-macos \
# RUN: %t/literals.s -o %t/literals.o
-# RUN: %lld -dylib -dead_strip --deduplicate-literals %t/literals.o -o %t/literals
+# RUN: %lld -dylib -dead_strip %t/literals.o -o %t/literals
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" --section="__DATA,str_ptrs" \
# RUN: --section="__TEXT,__literals" %t/literals | FileCheck %s --check-prefix=LIT
# LIT: Contents of (__TEXT,__cstring) section
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/not-terminated.s -o %t/not-terminated.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/relocs.s -o %t/relocs.o
-# RUN: not %lld -dylib --deduplicate-literals %t/not-terminated.o 2>&1 | FileCheck %s --check-prefix=TERM
-# RUN: not %lld -dylib --deduplicate-literals %t/relocs.o 2>&1 | FileCheck %s --check-prefix=RELOCS
+# RUN: not %lld -dylib %t/not-terminated.o 2>&1 | FileCheck %s --check-prefix=TERM
+# RUN: not %lld -dylib %t/relocs.o 2>&1 | FileCheck %s --check-prefix=RELOCS
# TERM: not-terminated.o:(__cstring+0x4): string is not null terminated
-# RELOCS: relocs.o contains relocations in __TEXT,__cstring, so LLD cannot deduplicate literals. Try re-running without --deduplicate-literals.
+# RELOCS: relocs.o contains relocations in __TEXT,__cstring, so LLD cannot deduplicate strings. Try re-running with --no-deduplicate-strings.
#--- not-terminated.s
.cstring
# RUN: rm -rf %t; split-file %s %t
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/qux.s -o %t/qux.o
-# RUN: %lld -dylib --deduplicate-literals %t/test.o %t/qux.o -o %t/test
+# RUN: %lld -dylib %t/test.o %t/qux.o -o %t/test
# RUN: llvm-objdump --macho --section="__TEXT,__literals" --section="__DATA,ptrs" --syms %t/test | FileCheck %s
# RUN: llvm-readobj --section-headers %t/test | FileCheck %s --check-prefix=HEADER
-## Make sure literal deduplication can be overridden or that the later flag wins.
-# RUN: %lld -dylib --deduplicate-literals -no_deduplicate %t/test.o %t/qux.o -o %t/no-dedup-test
-# RUN: llvm-objdump --macho --section="__TEXT,__literals" --section="__DATA,ptrs" %t/no-dedup-test | FileCheck %s --check-prefix=NO-DEDUP
-
-# RUN: %lld -dylib -no_deduplicate --deduplicate-literals %t/test.o %t/qux.o -o %t/test
+# RUN: %lld -dylib -no_deduplicate %t/test.o %t/qux.o -o %t/test
# RUN: llvm-objdump --macho --section="__TEXT,__literals" --section="__DATA,ptrs" --syms %t/test | FileCheck %s
# RUN: llvm-readobj --section-headers %t/test | FileCheck %s --check-prefix=HEADER
-# NO-DEDUP-NOT: Contents of (__TEXT,__literals) section
-# NO-DEDUP: Contents of (__DATA,ptrs) section
-# NO-DEDUP-NEXT: __TEXT:__literal16:0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef
-# NO-DEDUP-NEXT: __TEXT:__literal16:0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef
-# NO-DEDUP-NEXT: __TEXT:__literal16:0xfeedface 0xfeedface 0xfeedface 0xfeedface
-# NO-DEDUP-NEXT: __TEXT:__literal16:0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef
-# NO-DEDUP-NEXT: __TEXT:__literal8:0xdeadbeef 0xdeadbeef
-# NO-DEDUP-NEXT: __TEXT:__literal8:0xdeadbeef 0xdeadbeef
-# NO-DEDUP-NEXT: __TEXT:__literal8:0xfeedface 0xfeedface
-# NO-DEDUP-NEXT: __TEXT:__literal8:0xdeadbeef 0xdeadbeef
-# NO-DEDUP-NEXT: __TEXT:__literal4:0xdeadbeef
-# NO-DEDUP-NEXT: __TEXT:__literal4:0xdeadbeef
-# NO-DEDUP-NEXT: __TEXT:__literal4:0xfeedface
-# NO-DEDUP-NEXT: __TEXT:__literal4:0xdeadbeef
-
# CHECK: Contents of (__TEXT,__literals) section
# CHECK-NEXT: [[#%.16x,DEADBEEF16:]] ef be ad de ef be ad de ef be ad de ef be ad de
# CHECK-NEXT: [[#%.16x,FEEDFACE16:]] ce fa ed fe ce fa ed fe ce fa ed fe ce fa ed fe
# RUN: %lld -dylib %t/baz.o -o %t/libbaz.dylib
# RUN: %lld -demangle -map %t/map %t/test.o %t/foo.o %t/c-string-literal.o \
-# RUN: %t/libbaz.dylib --time-trace -o %t/test
+# RUN: %t/libbaz.dylib --time-trace -o %t/test --no-deduplicate-strings
# RUN: llvm-objdump --syms --section-headers %t/test > %t/objdump
## Check that symbols in cstring sections aren't emitted
## Also check that we don't have redundant EH_Frame symbols (regression test)
# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %t/strings.s -o %t/strings.o
# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %t/main.s -o %t/main.o
-# RUN: %lld -arch arm64 -lSystem -o %t.out %t/strings.o %t/main.o
+# RUN: %lld -arch arm64 -lSystem -o %t.out %t/strings.o %t/main.o --no-deduplicate-strings
# RUN: llvm-otool -vs __TEXT __cstring %t.out | FileCheck %s --check-prefix=CSTRING
# RUN: llvm-otool -vs __TEXT __objc_methname %t.out | FileCheck %s --check-prefix=METHNAME
-# RUN: %lld -arch arm64 -lSystem -o %t/duplicates %t/strings.o %t/strings.o %t/main.o --deduplicate-literals
+# RUN: %lld -arch arm64 -lSystem -o %t/duplicates %t/strings.o %t/strings.o %t/main.o
# RUN: llvm-otool -vs __TEXT __cstring %t/duplicates | FileCheck %s --check-prefix=CSTRING
# RUN: llvm-otool -vs __TEXT __objc_methname %t/duplicates | FileCheck %s --check-prefix=METHNAME