From 432030e843bf124b4d285874362b6fd00446dd56 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Wed, 27 Mar 2019 23:52:22 +0000 Subject: [PATCH] [ELF] Dump symbols ordered by profiled guided section layout to file. Patch by Tiancong Wang. In D36351, Call-Chain Clustering (C3) heuristic is implemented with option --call-graph-ordering-file . This patch adds a flag --print-symbol-order= to LLD, and when specified, it prints out the symbols ordered by the heuristics to the file. The symbols printout is helpful to those who want to understand the heuristics and want to reproduce the ordering with --symbol-ordering-file in later pass. Differential Revision: https://reviews.llvm.org/D59311 llvm-svn: 357133 --- lld/ELF/CallGraphSort.cpp | 21 +++++++++++++++++++ lld/ELF/Config.h | 1 + lld/ELF/Driver.cpp | 2 ++ lld/ELF/Options.td | 3 +++ lld/test/ELF/cgprofile-print.s | 37 +++++++++++++++++++++++++++++++++ lld/test/ELF/cgprofile-reproduce.s | 42 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 106 insertions(+) create mode 100644 lld/test/ELF/cgprofile-print.s create mode 100644 lld/test/ELF/cgprofile-reproduce.s diff --git a/lld/ELF/CallGraphSort.cpp b/lld/ELF/CallGraphSort.cpp index 2e50c50..8550177 100644 --- a/lld/ELF/CallGraphSort.cpp +++ b/lld/ELF/CallGraphSort.cpp @@ -226,6 +226,27 @@ DenseMap CallGraphSort::run() { for (int SecIndex : C.Sections) OrderMap[Sections[SecIndex]] = CurOrder++; + if (!Config->PrintSymbolOrder.empty()) { + std::error_code EC; + raw_fd_ostream OS(Config->PrintSymbolOrder, EC, sys::fs::F_None); + if (EC) { + error("cannot open " + Config->PrintSymbolOrder + ": " + EC.message()); + return OrderMap; + } + + // Print the symbols ordered by C3, in the order of increasing CurOrder + // Instead of sorting all the OrderMap, just repeat the loops above. + for (const Cluster &C : Clusters) + for (int SecIndex : C.Sections) + // Search all the symbols in the file of the section + // and find out a Defined symbol with name that is within the section. + for (Symbol *Sym: Sections[SecIndex]->File->getSymbols()) + if (!Sym->isSection()) // Filter out section-type symbols here. + if (auto *D = dyn_cast(Sym)) + if (Sections[SecIndex] == D->Section) + OS << Sym->getName() << "\n"; + } + return OrderMap; } diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index a6b96b4..b791723 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -101,6 +101,7 @@ struct Configuration { llvm::StringRef OptRemarksFilename; llvm::StringRef OptRemarksPasses; llvm::StringRef ProgName; + llvm::StringRef PrintSymbolOrder; llvm::StringRef SoName; llvm::StringRef Sysroot; llvm::StringRef ThinLTOCacheDir; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index c36494d..fc2df90 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -836,6 +836,8 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { 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->PrintSymbolOrder = + Args.getLastArgValue(OPT_print_symbol_order); Config->Rpath = getRpath(Args); Config->Relocatable = Args.hasArg(OPT_relocatable); Config->SaveTemps = Args.hasArg(OPT_save_temps); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index 968cf19..e0f3fbe 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -274,6 +274,9 @@ defm print_icf_sections: B<"print-icf-sections", "List identical folded sections", "Do not list identical folded sections (default)">; +defm print_symbol_order: Eq<"print-symbol-order", + "Print a symbol order specified by --call-graph-ordering-file into the speficied file">; + def pop_state: F<"pop-state">, HelpText<"Undo the effect of -push-state">; diff --git a/lld/test/ELF/cgprofile-print.s b/lld/test/ELF/cgprofile-print.s new file mode 100644 index 0000000..b103ef5 --- /dev/null +++ b/lld/test/ELF/cgprofile-print.s @@ -0,0 +1,37 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "A B 5" > %t.call_graph +# RUN: echo "B C 50" >> %t.call_graph +# RUN: echo "C D 40" >> %t.call_graph +# RUN: echo "D B 10" >> %t.call_graph +# RUN: ld.lld -e A %t --call-graph-ordering-file %t.call_graph -o %t2 --print-symbol-order=%t3 +# RUN: FileCheck %s --input-file %t3 + +# CHECK: B +# CHECK-NEXT: C +# CHECK-NEXT: D +# CHECK-NEXT: A + +.section .text.A,"ax",@progbits +.globl A +A: + nop + +.section .text.B,"ax",@progbits +.globl B +B: + nop + +.section .text.C,"ax",@progbits +.globl C +C: + nop + +.section .text.D,"ax",@progbits +.globl D +D: + nop + + + diff --git a/lld/test/ELF/cgprofile-reproduce.s b/lld/test/ELF/cgprofile-reproduce.s new file mode 100644 index 0000000..224127c --- /dev/null +++ b/lld/test/ELF/cgprofile-reproduce.s @@ -0,0 +1,42 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "A B 5" > %t.call_graph +# RUN: echo "B C 50" >> %t.call_graph +# RUN: echo "C D 40" >> %t.call_graph +# RUN: echo "D B 10" >> %t.call_graph +# RUN: ld.lld -e A %t --call-graph-ordering-file %t.call_graph -o %t2 --print-symbol-order=%t3 +# RUN: ld.lld -e A %t --symbol-ordering-file %t3 -o %t2 +# RUN: llvm-readobj -symbols %t2 | FileCheck %s + +# CHECK: Name: A +# CHECK-NEXT: Value: 0x201003 +# CHECK: Name: B +# CHECK-NEXT: Value: 0x201000 +# CHECK: Name: C +# CHECK-NEXT: Value: 0x201001 +# CHECK: Name: D +# CHECK-NEXT: Value: 0x201002 + +.section .text.A,"ax",@progbits +.globl A +A: + nop + +.section .text.B,"ax",@progbits +.globl B +B: + nop + +.section .text.C,"ax",@progbits +.globl C +C: + nop + +.section .text.D,"ax",@progbits +.globl D +D: + nop + + + -- 2.7.4