[lld] r337640 - ELF: Read address significance tables with --icf=all.
Peter Collingbourne via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 20 19:14:59 PDT 2018
Author: pcc
Date: Fri Jul 20 19:14:59 2018
New Revision: 337640
URL: http://llvm.org/viewvc/llvm-project?rev=337640&view=rev
Log:
ELF: Read address significance tables with --icf=all.
Under --icf=all we now only apply KeepUnique to non-executable
address-significant sections. This has the effect of making --icf=all
mean unsafe ICF for executable sections and safe ICF for non-executable
sections.
With this change the meaning of the KeepUnique bit changes to
"does the current ICF mode (together with the --keep-unique and
--ignore-data-address-equality flags) require this section to be
kept unique".
Differential Revision: https://reviews.llvm.org/D49626
Modified:
lld/trunk/ELF/Driver.cpp
lld/trunk/ELF/ICF.cpp
lld/trunk/test/ELF/icf-safe.s
Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=337640&r1=337639&r2=337640&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Fri Jul 20 19:14:59 2018
@@ -1235,14 +1235,15 @@ template <class ELFT> static void demote
}
}
-static bool keepUnique(Symbol *S) {
- if (auto *D = dyn_cast_or_null<Defined>(S)) {
- if (D->Section) {
- D->Section->KeepUnique = true;
- return true;
- }
- }
- return false;
+// The section referred to by S is considered address-significant. Set the
+// KeepUnique flag on the section if appropriate.
+static void markAddrsig(Symbol *S) {
+ if (auto *D = dyn_cast_or_null<Defined>(S))
+ if (D->Section)
+ // We don't need to keep text sections unique under --icf=all even if they
+ // are address-significant.
+ if (Config->ICF == ICFLevel::Safe || !(D->Section->Flags & SHF_EXECINSTR))
+ D->Section->KeepUnique = true;
}
// Record sections that define symbols mentioned in --keep-unique <symbol>
@@ -1252,41 +1253,48 @@ template <class ELFT>
static void findKeepUniqueSections(opt::InputArgList &Args) {
for (auto *Arg : Args.filtered(OPT_keep_unique)) {
StringRef Name = Arg->getValue();
- if (!keepUnique(Symtab->find(Name)))
+ auto *D = dyn_cast_or_null<Defined>(Symtab->find(Name));
+ if (!D || !D->Section) {
warn("could not find symbol " + Name + " to keep unique");
+ continue;
+ }
+ D->Section->KeepUnique = true;
}
- if (Config->ICF == ICFLevel::Safe) {
- // Symbols in the dynsym could be address-significant in other executables
- // or DSOs, so we conservatively mark them as address-significant.
- for (Symbol *S : Symtab->getSymbols())
- if (S->includeInDynsym())
- keepUnique(S);
+ // --icf=all --ignore-data-address-equality means that we can ignore
+ // the dynsym and address-significance tables entirely.
+ if (Config->ICF == ICFLevel::All && Config->IgnoreDataAddressEquality)
+ return;
+
+ // Symbols in the dynsym could be address-significant in other executables
+ // or DSOs, so we conservatively mark them as address-significant.
+ for (Symbol *S : Symtab->getSymbols())
+ if (S->includeInDynsym())
+ markAddrsig(S);
- // Visit the address-significance table in each object file and mark each
- // referenced symbol as address-significant.
- for (InputFile *F : ObjectFiles) {
- auto *Obj = cast<ObjFile<ELFT>>(F);
- ArrayRef<Symbol *> Syms = Obj->getSymbols();
- if (Obj->AddrsigSec) {
- ArrayRef<uint8_t> Contents =
- check(Obj->getObj().getSectionContents(Obj->AddrsigSec));
- 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(F) + ": could not decode addrsig section: " + Err);
- keepUnique(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)
- keepUnique(S);
+ // Visit the address-significance table in each object file and mark each
+ // referenced symbol as address-significant.
+ for (InputFile *F : ObjectFiles) {
+ auto *Obj = cast<ObjFile<ELFT>>(F);
+ ArrayRef<Symbol *> Syms = Obj->getSymbols();
+ if (Obj->AddrsigSec) {
+ ArrayRef<uint8_t> Contents =
+ check(Obj->getObj().getSectionContents(Obj->AddrsigSec));
+ 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(F) + ": could not decode addrsig section: " + Err);
+ 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);
}
}
}
Modified: lld/trunk/ELF/ICF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ICF.cpp?rev=337640&r1=337639&r2=337640&view=diff
==============================================================================
--- lld/trunk/ELF/ICF.cpp (original)
+++ lld/trunk/ELF/ICF.cpp Fri Jul 20 19:14:59 2018
@@ -172,12 +172,6 @@ static bool isEligible(InputSection *S)
!S->Name.startswith(".data.rel.ro."))
return false;
- // Don't merge read only data sections unless
- // --ignore-data-address-equality or --icf=safe was passed.
- if (!(S->Flags & SHF_EXECINSTR) &&
- !(Config->IgnoreDataAddressEquality || Config->ICF == ICFLevel::Safe))
- return false;
-
// Don't merge synthetic sections as their Data member is not valid and empty.
// The Data member needs to be valid for ICF as it is used by ICF to determine
// the equality of section contents.
Modified: lld/trunk/test/ELF/icf-safe.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/icf-safe.s?rev=337640&r1=337639&r2=337640&view=diff
==============================================================================
--- lld/trunk/test/ELF/icf-safe.s (original)
+++ lld/trunk/test/ELF/icf-safe.s Fri Jul 20 19:14:59 2018
@@ -6,6 +6,8 @@
# RUN: ld.lld %t1.o %t2.o -o %t2 --icf=safe --print-icf-sections | FileCheck %s
# RUN: ld.lld %t1.o %t2.o -o %t3 --icf=safe --print-icf-sections -shared | FileCheck --check-prefix=EXPORT %s
# RUN: ld.lld %t1.o %t2.o -o %t3 --icf=safe --print-icf-sections --export-dynamic | FileCheck --check-prefix=EXPORT %s
+# RUN: ld.lld %t1.o %t2.o -o %t2 --icf=all --print-icf-sections | FileCheck --check-prefix=ALL %s
+# RUN: ld.lld %t1.o %t2.o -o %t2 --icf=all --print-icf-sections --export-dynamic | FileCheck --check-prefix=ALL-EXPORT %s
# RUN: ld.lld %t1copy.o -o %t4 --icf=safe 2>&1 | FileCheck --check-prefix=OBJCOPY %s
# CHECK-NOT: selected section {{.*}}:(.rodata.l1)
@@ -26,6 +28,28 @@
# CHECK-NOT: selected section {{.*}}:(.text.non_addrsig{{.}})
+# With --icf=all address-significance implies keep-unique only for rodata, not
+# text.
+# ALL-NOT: selected section {{.*}}:(.rodata.l1)
+# ALL: selected section {{.*}}:(.rodata.l3)
+# ALL: removing identical section {{.*}}:(.rodata.l4)
+
+# ALL: selected section {{.*}}:(.text.f3)
+# ALL: removing identical section {{.*}}:(.text.f4)
+
+# ALL: selected section {{.*}}:(.text.f1)
+# ALL: removing identical section {{.*}}:(.text.f2)
+# ALL: removing identical section {{.*}}:(.text.non_addrsig1)
+# ALL: removing identical section {{.*}}:(.text.non_addrsig2)
+
+# ALL-NOT: selected section {{.*}}:(.rodata.h1)
+# ALL: selected section {{.*}}:(.rodata.h3)
+# ALL: removing identical section {{.*}}:(.rodata.h4)
+
+# ALL-NOT: selected section {{.*}}:(.rodata.g1)
+# ALL: selected section {{.*}}:(.rodata.g3)
+# ALL: removing identical section {{.*}}:(.rodata.g4)
+
# llvm-mc normally emits an empty .text section into every object file. Since
# nothing actually refers to it via a relocation, it doesn't have any associated
# symbols (thus nor can anything refer to it via a relocation, making it safe to
@@ -44,6 +68,27 @@
# EXPORT: removing identical section {{.*}}:(.text)
# EXPORT-NOT: selected section
+# If --icf=all is specified when exporting we can also merge the exported text
+# sections, but not the exported rodata.
+# ALL-EXPORT-NOT: selected section
+# ALL-EXPORT: selected section {{.*}}:(.rodata.l3)
+# ALL-EXPORT: removing identical section {{.*}}:(.rodata.l4)
+# ALL-EXPORT-NOT: selected section
+# ALL-EXPORT: selected section {{.*}}:(.text.f3)
+# ALL-EXPORT: removing identical section {{.*}}:(.text.f4)
+# ALL-EXPORT-NOT: selected section
+# ALL-EXPORT: selected section {{.*}}:(.text.f1)
+# ALL-EXPORT: removing identical section {{.*}}:(.text.f2)
+# ALL-EXPORT: removing identical section {{.*}}:(.text.non_addrsig1)
+# ALL-EXPORT: removing identical section {{.*}}:(.text.non_addrsig2)
+# ALL-EXPORT-NOT: selected section
+# ALL-EXPORT: selected section {{.*}}:(.rodata.h3)
+# ALL-EXPORT: removing identical section {{.*}}:(.rodata.h4)
+# ALL-EXPORT-NOT: selected section
+# ALL-EXPORT: selected section {{.*}}:(.text)
+# ALL-EXPORT: removing identical section {{.*}}:(.text)
+# ALL-EXPORT-NOT: selected section
+
# OBJCOPY: --icf=safe is incompatible with object files created using objcopy or ld -r
.section .text.f1,"ax", at progbits
More information about the llvm-commits
mailing list