diff options
author | James Henderson <jh7370@my.bristol.ac.uk> | 2018-02-01 16:00:46 +0000 |
---|---|---|
committer | James Henderson <jh7370@my.bristol.ac.uk> | 2018-02-01 16:00:46 +0000 |
commit | 9c6e2fd5a4d37df0cf82486e0648583650b297f9 (patch) | |
tree | 5b9d358ddeb51a37a2668e9ba17aaa05802689d8 | |
parent | 91af9048b26b02b82b4eee637dabb6c81e275905 (diff) | |
download | bcm5719-llvm-9c6e2fd5a4d37df0cf82486e0648583650b297f9.tar.gz bcm5719-llvm-9c6e2fd5a4d37df0cf82486e0648583650b297f9.zip |
[ELF] Add --print-icf-sections flag
Currently ICF information is output through stderr if the "--verbose"
flag is used. This differs to Gold for example, which uses an explicit
flag to output this to stdout. This commit adds the
"--print-icf-sections" and "--no-print-icf-sections" flags and changes
the output message format for clarity and consistency with
"--print-gc-sections". These messages are still output to stderr if
using the verbose flag. However to avoid intermingled message output to
console, this will not occur when the "--print-icf-sections" flag is
used.
Existing tests have been modified to expect the new message format from
stderr.
Patch by Owen Reynolds.
Differential Revision: https://reviews.llvm.org/D42375
Reviewers: ruiu, rafael
Reviewed by:
llvm-svn: 323976
-rw-r--r-- | lld/ELF/Config.h | 1 | ||||
-rw-r--r-- | lld/ELF/Driver.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/ICF.cpp | 18 | ||||
-rw-r--r-- | lld/ELF/Options.td | 6 | ||||
-rw-r--r-- | lld/test/ELF/Inputs/print-icf.s | 9 | ||||
-rw-r--r-- | lld/test/ELF/icf-absolute.s | 4 | ||||
-rw-r--r-- | lld/test/ELF/icf-comdat.s | 4 | ||||
-rw-r--r-- | lld/test/ELF/icf-i386.s | 6 | ||||
-rw-r--r-- | lld/test/ELF/icf-merge-sec.s | 4 | ||||
-rw-r--r-- | lld/test/ELF/icf-merge.s | 6 | ||||
-rw-r--r-- | lld/test/ELF/icf-non-mergeable.s | 4 | ||||
-rw-r--r-- | lld/test/ELF/icf-none.s | 2 | ||||
-rw-r--r-- | lld/test/ELF/icf1.s | 4 | ||||
-rw-r--r-- | lld/test/ELF/icf2.s | 4 | ||||
-rw-r--r-- | lld/test/ELF/icf3.s | 4 | ||||
-rw-r--r-- | lld/test/ELF/icf4.s | 4 | ||||
-rw-r--r-- | lld/test/ELF/icf5.s | 4 | ||||
-rw-r--r-- | lld/test/ELF/icf6.s | 4 | ||||
-rw-r--r-- | lld/test/ELF/icf7.s | 4 | ||||
-rw-r--r-- | lld/test/ELF/icf9.s | 8 | ||||
-rw-r--r-- | lld/test/ELF/print-icf.s | 48 |
21 files changed, 115 insertions, 35 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 28326a84cf1..0fa1564f1ac 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -140,6 +140,7 @@ struct Configuration { bool OptRemarksWithHotness; bool Pie; bool PrintGcSections; + bool PrintIcfSections; bool Relocatable; bool SaveTemps; bool SingleRoRx; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index bbf28ade61d..4b7f90253f2 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -643,6 +643,8 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { Config->OrphanHandling = getOrphanHandling(Args); Config->OutputFile = Args.getLastArgValue(OPT_o); Config->Pie = Args.hasFlag(OPT_pie, OPT_nopie, false); + Config->PrintIcfSections = + Args.hasFlag(OPT_print_icf_sections, OPT_no_print_icf_sections, false); Config->PrintGcSections = Args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false); Config->Rpath = getRpath(Args); diff --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp index bcc901bfa95..a4dab446773 100644 --- a/lld/ELF/ICF.cpp +++ b/lld/ELF/ICF.cpp @@ -424,14 +424,28 @@ template <class ELFT> void ICF<ELFT>::run() { log("ICF needed " + Twine(Cnt) + " iterations"); + auto Print = [&](const Twine &Prefix, size_t I) { + if (!Config->Verbose && !Config->PrintIcfSections) + return; + std::string Filename = + Sections[I]->File ? Sections[I]->File->getName() : "<internal>"; + std::string S = (Prefix + " section '" + Sections[I]->Name + + "' from file '" + Filename + "'") + .str(); + if (Config->PrintIcfSections) + message(S); + else + log(S); + }; + // Merge sections by the equivalence class. forEachClass([&](size_t Begin, size_t End) { if (End - Begin == 1) return; - log("selected " + Sections[Begin]->Name); + Print("selected", Begin); for (size_t I = Begin + 1; I < End; ++I) { - log(" removed " + Sections[I]->Name); + Print(" removing identical", I); Sections[Begin]->replace(Sections[I]); } }); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index 86aa99eaf44..d642c5e0988 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -222,6 +222,9 @@ def no_omagic: Flag<["--"], "no-omagic">, MetaVarName<"<magic>">, def no_print_gc_sections: F<"no-print-gc-sections">, HelpText<"Do not list removed unused sections">; +def no_print_icf_sections: F<"no-print-icf-sections">, + HelpText<"Do not list identical folded sections">; + def no_rosegment: F<"no-rosegment">, HelpText<"Do not put read-only non-executable sections in their own segment">; @@ -251,6 +254,9 @@ def pie: F<"pie">, HelpText<"Create a position independent executable">; def print_gc_sections: F<"print-gc-sections">, HelpText<"List removed unused sections">; +def print_icf_sections: F<"print-icf-sections">, + HelpText<"List identical folded sections">; + def print_map: F<"print-map">, HelpText<"Print a link map to the standard output">; diff --git a/lld/test/ELF/Inputs/print-icf.s b/lld/test/ELF/Inputs/print-icf.s new file mode 100644 index 00000000000..a67bee2f185 --- /dev/null +++ b/lld/test/ELF/Inputs/print-icf.s @@ -0,0 +1,9 @@ +.section .text.f6, "ax"
+f6:
+ mov $60, %rax
+ mov $42, %rdi
+ syscall
+
+ .section .text.f7, "ax"
+f7:
+ mov $0, %rax
diff --git a/lld/test/ELF/icf-absolute.s b/lld/test/ELF/icf-absolute.s index 09f6790907a..42d2ebedd93 100644 --- a/lld/test/ELF/icf-absolute.s +++ b/lld/test/ELF/icf-absolute.s @@ -4,8 +4,8 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-absolute.s -o %t2 # RUN: ld.lld %t %t2 -o %t3 --icf=all --verbose 2>&1 | FileCheck %s -# CHECK: selected .text.f1 -# CHECK: removed .text.f2 +# CHECK: selected section '.text.f1' from file +# CHECK: removing identical section '.text.f2' from file .globl _start, f1, f2 _start: diff --git a/lld/test/ELF/icf-comdat.s b/lld/test/ELF/icf-comdat.s index aab6a00f484..029088c26e0 100644 --- a/lld/test/ELF/icf-comdat.s +++ b/lld/test/ELF/icf-comdat.s @@ -3,8 +3,8 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t # RUN: ld.lld %t -o %t2 --icf=all --verbose 2>&1 | FileCheck %s -# CHECK: selected .text.f1 -# CHECK: removed .text.f2 +# CHECK: selected section '.text.f1' from file [[T:'.*']] +# CHECK: removing identical section '.text.f2' from file [[T]] .globl _start, f1, f2 _start: diff --git a/lld/test/ELF/icf-i386.s b/lld/test/ELF/icf-i386.s index b01e0503d40..c00739b994a 100644 --- a/lld/test/ELF/icf-i386.s +++ b/lld/test/ELF/icf-i386.s @@ -4,9 +4,9 @@ # RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %s -o %t # RUN: ld.lld %t -o %t2 --icf=all --verbose 2>&1 | FileCheck %s -# CHECK: selected .text.f1 -# CHECK: removed .text.f2 -# CHECK-NOT: removed .text.f3 +# CHECK: selected section '.text.f1' from file [[T:'.*']] +# CHECK: removing identical section '.text.f2' from file [[T]] +# CHECK-NOT: removing identical section '.text.f3' from file [[T]] .globl _start, f1, f2, f3 _start: diff --git a/lld/test/ELF/icf-merge-sec.s b/lld/test/ELF/icf-merge-sec.s index 1e866a0caa4..14114f0ee25 100644 --- a/lld/test/ELF/icf-merge-sec.s +++ b/lld/test/ELF/icf-merge-sec.s @@ -4,8 +4,8 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-merge-sec.s -o %t2 # RUN: ld.lld %t %t2 -o %t3 --icf=all --verbose 2>&1 | FileCheck %s -# CHECK: selected .text.f1 -# CHECK: removed .text.f2 +# CHECK: selected section '.text.f1' from file +# CHECK: removing identical section '.text.f2' from file .section .rodata.str,"aMS",@progbits,1 .asciz "foo" diff --git a/lld/test/ELF/icf-merge.s b/lld/test/ELF/icf-merge.s index 06e852fe9dd..e5cb8be8d07 100644 --- a/lld/test/ELF/icf-merge.s +++ b/lld/test/ELF/icf-merge.s @@ -10,10 +10,10 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-merge3.s -o %t3 # RUN: ld.lld %t %t3 -o %t3.out --icf=all --verbose 2>&1 | FileCheck --check-prefix=NOMERGE %s -# CHECK: selected .text.f1 -# CHECK: removed .text.f2 +# CHECK: selected section '.text.f1' from file +# CHECK: removing identical section '.text.f2' from file -# NOMERGE-NOT: selected .text.f +# NOMERGE-NOT: selected section '.text.f .section .rodata.str,"aMS",@progbits,1 foo: diff --git a/lld/test/ELF/icf-non-mergeable.s b/lld/test/ELF/icf-non-mergeable.s index 48ba2008cac..cefe36070c3 100644 --- a/lld/test/ELF/icf-non-mergeable.s +++ b/lld/test/ELF/icf-non-mergeable.s @@ -10,8 +10,8 @@ // RUN: ld.lld %t1 %t2 -o %t3 --icf=all --verbose 2>&1 | FileCheck %s -// CHECK-NOT: selected .text.f1 -// CHECK-NOT: removed .text.f2 +// CHECK-NOT: selected section '.text.f1' +// CHECK-NOT: removing identical section '.text.f2' .globl _start, f1, f2, d1, d2 _start: diff --git a/lld/test/ELF/icf-none.s b/lld/test/ELF/icf-none.s index 9ec1406de8a..ed3e2dcea30 100644 --- a/lld/test/ELF/icf-none.s +++ b/lld/test/ELF/icf-none.s @@ -3,7 +3,7 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t # RUN: ld.lld %t -o %t2 --icf=all --icf=none --verbose 2>&1 | FileCheck %s -# CHECK-NOT: selected .text.f1 +# CHECK-NOT: selected section '.text.f1' .globl _start, f1, f2 _start: diff --git a/lld/test/ELF/icf1.s b/lld/test/ELF/icf1.s index e2562b5a83e..fe207031493 100644 --- a/lld/test/ELF/icf1.s +++ b/lld/test/ELF/icf1.s @@ -3,8 +3,8 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t # RUN: ld.lld %t -o %t2 --icf=all --verbose 2>&1 | FileCheck %s -# CHECK: selected .text.f1 -# CHECK: removed .text.f2 +# CHECK: selected section '.text.f1' from file [[T:'.*']] +# CHECK: removing identical section '.text.f2' from file [[T]] .globl _start, f1, f2 _start: diff --git a/lld/test/ELF/icf2.s b/lld/test/ELF/icf2.s index fd0a311cbd1..9bebfb8f9c6 100644 --- a/lld/test/ELF/icf2.s +++ b/lld/test/ELF/icf2.s @@ -4,8 +4,8 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/icf2.s -o %t2 # RUN: ld.lld %t1 %t2 -o %t --icf=all --verbose 2>&1 | FileCheck %s -# CHECK: selected .text.f1 -# CHECK: removed .text.f2 +# CHECK: selected section '.text.f1' from file +# CHECK: removing identical section '.text.f2' from file .globl _start, f1, f2 _start: diff --git a/lld/test/ELF/icf3.s b/lld/test/ELF/icf3.s index 40067cefb20..d2a7b40d92f 100644 --- a/lld/test/ELF/icf3.s +++ b/lld/test/ELF/icf3.s @@ -4,8 +4,8 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/icf2.s -o %t2 # RUN: ld.lld %t1 %t2 -o %t --icf=all --verbose 2>&1 | FileCheck %s -# CHECK-NOT: Selected .text.f1 -# CHECK-NOT: Selected .text.f2 +# CHECK-NOT: selected section '.text.f1' from file +# CHECK-NOT: selected section '.text.f2' from file .globl _start, f1, f2 _start: diff --git a/lld/test/ELF/icf4.s b/lld/test/ELF/icf4.s index b7f40e80573..b44e71e83ca 100644 --- a/lld/test/ELF/icf4.s +++ b/lld/test/ELF/icf4.s @@ -3,8 +3,8 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t # RUN: ld.lld %t -o %t2 --icf=all --verbose 2>&1 | FileCheck %s -# CHECK-NOT: Selected .text.f1 -# CHECK-NOT: Selected .text.f2 +# CHECK-NOT: selected section '.text.f1' +# CHECK-NOT: selected section '.text.f2' .globl _start, f1, f2 _start: diff --git a/lld/test/ELF/icf5.s b/lld/test/ELF/icf5.s index 749cc5e923a..bdc28c1c2c5 100644 --- a/lld/test/ELF/icf5.s +++ b/lld/test/ELF/icf5.s @@ -3,8 +3,8 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t # RUN: ld.lld %t -o %t2 --icf=all --verbose 2>&1 | FileCheck %s -# CHECK-NOT: Selected .text.f1 -# CHECK-NOT: Selected .text.f2 +# CHECK-NOT: selected section '.text.f1' +# CHECK-NOT: selected section '.text.f2' .globl _start, f1, f2 _start: diff --git a/lld/test/ELF/icf6.s b/lld/test/ELF/icf6.s index 6420868523b..97449ca6530 100644 --- a/lld/test/ELF/icf6.s +++ b/lld/test/ELF/icf6.s @@ -3,8 +3,8 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t # RUN: ld.lld %t -o %t2 --icf=all --verbose 2>&1 | FileCheck %s -# CHECK-NOT: Selected .text.f1 -# CHECK-NOT: Selected .text.f2 +# CHECK-NOT: selected section '.text.f1' +# CHECK-NOT: selected section '.text.f2' .globl _start, f1, f2 _start: diff --git a/lld/test/ELF/icf7.s b/lld/test/ELF/icf7.s index 00fca793aee..3e78c99184c 100644 --- a/lld/test/ELF/icf7.s +++ b/lld/test/ELF/icf7.s @@ -4,8 +4,8 @@ # RUN: ld.lld %t -o %t2 --icf=all --verbose 2>&1 | FileCheck %s # RUN: llvm-objdump -t %t2 | FileCheck -check-prefix=ALIGN %s -# CHECK: selected .text.f1 -# CHECK: removed .text.f2 +# CHECK: selected section '.text.f1' from file [[T:'.*']] +# CHECK: removing identical section '.text.f2' from file [[T]] # ALIGN: 0000000000201000 .text 00000000 _start # ALIGN: 0000000000201100 .text 00000000 f1 diff --git a/lld/test/ELF/icf9.s b/lld/test/ELF/icf9.s index bfa18914beb..652fb361a3c 100644 --- a/lld/test/ELF/icf9.s +++ b/lld/test/ELF/icf9.s @@ -7,15 +7,15 @@ # SEC: .rodata PROGBITS 0000000000200120 000120 000002 00 A 0 0 1 -# CHECK-NOT: selected .rodata.d1 -# CHECK-NOT: selected .rodata.d2 +# CHECK-NOT: selected section '.rodata.d1' +# CHECK-NOT: selected section '.rodata.d2' # We do merge rodata if passed --icf-data # RUN: ld.lld %t -o %t2 --icf=all --verbose --ignore-data-address-equality 2>&1 | FileCheck --check-prefix=DATA %s # RUN: llvm-readelf -S -W %t2 | FileCheck --check-prefix=DATA-SEC %s -# DATA: selected .rodata.d1 -# DATA: removed .rodata.d2 +# DATA: selected section '.rodata.d1' from file [[T:'.*']] +# DATA: removing identical section '.rodata.d2' from file [[T]] # DATA-SEC: .rodata PROGBITS 0000000000200120 000120 000001 00 A 0 0 1 diff --git a/lld/test/ELF/print-icf.s b/lld/test/ELF/print-icf.s new file mode 100644 index 00000000000..c1e58aaf5b2 --- /dev/null +++ b/lld/test/ELF/print-icf.s @@ -0,0 +1,48 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/print-icf.s -o %t1 +# RUN: ld.lld %t %t1 -o %t2 --icf=all --print-icf-sections | FileCheck %s +# RUN: ld.lld %t %t1 -o %t2 --icf=all --no-print-icf-sections --print-icf-sections | FileCheck %s +# RUN: ld.lld %t %t1 -o %t2 --icf=all --print-icf-sections --no-print-icf-sections | FileCheck -allow-empty -check-prefix=PRINT %s + +# CHECK: selected section '.text.f2' from file [[T:'.*']] +# CHECK: removing identical section '.text.f4' from file [[T]] +# CHECK: removing identical section '.text.f7' from file [[T1:'.*']] +# CHECK: selected section '.text.f1' from file [[T]] +# CHECK: removing identical section '.text.f3' from file [[T]] +# CHECK: removing identical section '.text.f5' from file [[T]] +# CHECK: removing identical section '.text.f6' from file [[T1]] + +# PRINT-NOT: selected +# PRINT-NOT: removing + +.globl _start, f1, f2 +_start: + ret + +.section .text.f1, "ax" +f1: + mov $60, %rax + mov $42, %rdi + syscall + + .section .text.f2, "ax" +f2: + mov $0, %rax + +.section .text.f3, "ax" +f3: + mov $60, %rax + mov $42, %rdi + syscall + +.section .text.f4, "ax" +f4: + mov $0, %rax + +.section .text.f5, "ax" +f5: + mov $60, %rax + mov $42, %rdi + syscall |