forked from OSchip/llvm-project
[ELF] Implement --keep-unique option
The --keep-unique <symbol> option is taken from gold. The intention is that <symbol> will be prevented from being folded by ICF. Although not specifically mentioned in the documentation <symbol> only matches global symbols, with a warning if the symbol is not found. The implementation finds the Section defining <symbol> and removes it from the set of sections considered for ICF. Differential Revision: https://reviews.llvm.org/D46755 llvm-svn: 332332
This commit is contained in:
parent
559d1e34df
commit
dbef8cc67c
|
@ -1163,6 +1163,18 @@ template <class ELFT> static void demoteSymbols() {
|
|||
}
|
||||
}
|
||||
|
||||
// Record sections that define symbols mentioned in --keep-unique <symbol>
|
||||
// these sections are inelligible for ICF.
|
||||
static void findKeepUniqueSections(opt::InputArgList &Args) {
|
||||
for (auto *Arg : Args.filtered(OPT_keep_unique)) {
|
||||
StringRef Name = Arg->getValue();
|
||||
if (auto *Sym = dyn_cast_or_null<Defined>(Symtab->find(Name)))
|
||||
Sym->Section->KeepUnique = true;
|
||||
else
|
||||
warn("could not find symbol " + Name + " to keep unique");
|
||||
}
|
||||
}
|
||||
|
||||
// Do actual linking. Note that when this function is called,
|
||||
// all linker scripts have already been parsed.
|
||||
template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
||||
|
@ -1335,8 +1347,10 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
|||
markLive<ELFT>();
|
||||
demoteSymbols<ELFT>();
|
||||
mergeSections();
|
||||
if (Config->ICF)
|
||||
if (Config->ICF) {
|
||||
findKeepUniqueSections(Args);
|
||||
doIcf<ELFT>();
|
||||
}
|
||||
|
||||
// Read the callgraph now that we know what was gced or icfed
|
||||
if (auto *Arg = Args.getLastArg(OPT_call_graph_ordering_file))
|
||||
|
|
|
@ -162,7 +162,8 @@ template <class ELFT> static uint32_t getHash(InputSection *S) {
|
|||
|
||||
// Returns true if section S is subject of ICF.
|
||||
static bool isEligible(InputSection *S) {
|
||||
if (!S->Live || !(S->Flags & SHF_ALLOC) || (S->Flags & SHF_WRITE))
|
||||
if (!S->Live || S->KeepUnique || !(S->Flags & SHF_ALLOC) ||
|
||||
(S->Flags & SHF_WRITE))
|
||||
return false;
|
||||
|
||||
// Don't merge read only data sections unless
|
||||
|
|
|
@ -61,6 +61,9 @@ public:
|
|||
|
||||
unsigned Bss : 1;
|
||||
|
||||
// Set for sections that should not be folded by ICF.
|
||||
unsigned KeepUnique : 1;
|
||||
|
||||
// These corresponds to the fields in Elf_Shdr.
|
||||
uint32_t Alignment;
|
||||
uint64_t Flags;
|
||||
|
@ -85,8 +88,8 @@ protected:
|
|||
uint64_t Entsize, uint64_t Alignment, uint32_t Type,
|
||||
uint32_t Info, uint32_t Link)
|
||||
: Name(Name), Repl(this), SectionKind(SectionKind), Live(false),
|
||||
Bss(false), Alignment(Alignment), Flags(Flags), Entsize(Entsize),
|
||||
Type(Type), Link(Link), Info(Info) {}
|
||||
Bss(false), KeepUnique(false), Alignment(Alignment), Flags(Flags),
|
||||
Entsize(Entsize), Type(Type), Link(Link), Info(Info) {}
|
||||
};
|
||||
|
||||
// This corresponds to a section of an input file.
|
||||
|
|
|
@ -192,6 +192,8 @@ defm init: Eq<"init">, HelpText<"Specify an initializer function">,
|
|||
|
||||
defm just_symbols: Eq<"just-symbols">, HelpText<"Just link symbols">;
|
||||
|
||||
defm keep_unique: Eq<"keep-unique">, HelpText<"Do not fold this symbol during ICF">;
|
||||
|
||||
defm library: Eq<"library">, HelpText<"Root name of library to use">,
|
||||
MetaVarName<"<libName>">;
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
# REQUIRES: x86
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
|
||||
# RUN: ld.lld %t -o %t2 --icf=all --print-icf-sections | FileCheck %s
|
||||
# RUN: ld.lld %t -o %t2 --keep-unique f2 --keep-unique f4 --keep-unique f5 --icf=all --print-icf-sections 2>&1 | FileCheck %s -check-prefix=CHECK-KEEP
|
||||
|
||||
// Base case, expect only .text.f1 to be kept
|
||||
// CHECK: selected section {{.*}}:(.text.f1)
|
||||
// CHECK-NEXT: removing identical section {{.*}}:(.text.f2)
|
||||
// CHECK-NEXT: removing identical section {{.*}}:(.text.f3)
|
||||
// CHECK-NEXT: removing identical section {{.*}}:(.text.f4)
|
||||
// CHECK-NEXT: removing identical section {{.*}}:(.text.f5)
|
||||
|
||||
// With --keep-unique f2, f4 and f5 we expect only f3 and f5 to be removed.
|
||||
// f5 is not matched by --keep-unique as it is a local symbol.
|
||||
// CHECK-KEEP: warning: could not find symbol f5 to keep unique
|
||||
// CHECK-KEEP: selected section {{.*}}:(.text.f1)
|
||||
// CHECK-KEEP-NEXT: removing identical section {{.*}}:(.text.f3)
|
||||
// CHECK-KEEP-NEXT: removing identical section {{.*}}:(.text.f5)
|
||||
.globl _start, f1, f2, f3, f4
|
||||
_start:
|
||||
ret
|
||||
|
||||
.section .text.f1, "ax"
|
||||
f1:
|
||||
nop
|
||||
|
||||
.section .text.f2, "ax"
|
||||
f2:
|
||||
nop
|
||||
|
||||
.section .text.f3, "ax"
|
||||
f3:
|
||||
nop
|
||||
|
||||
.section .text.f4, "ax"
|
||||
f4:
|
||||
nop
|
||||
|
||||
# f5 is local, not found by --keep-unique f5
|
||||
.section .text.f5, "ax"
|
||||
f5:
|
||||
nop
|
Loading…
Reference in New Issue