diff --git a/lld/ELF/CallGraphSort.cpp b/lld/ELF/CallGraphSort.cpp --- a/lld/ELF/CallGraphSort.cpp +++ b/lld/ELF/CallGraphSort.cpp @@ -226,6 +226,26 @@ 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 *Symbol: Sections[SecIndex]->File->getSymbols()) + if (!Symbol->getName().empty()) + if (auto *D = dyn_cast(Symbol)) + if (Sections[SecIndex] == D->Section) + OS << Symbol->getName() << "\n"; + } return OrderMap; } diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -101,6 +101,7 @@ 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 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -828,6 +828,8 @@ 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); @@ -1470,6 +1472,9 @@ error("cannot open output file " + Config->OutputFile + ": " + E.message()); if (auto E = tryCreateFile(Config->MapFile)) error("cannot open map file " + Config->MapFile + ": " + E.message()); + // Fail early too if the symbol order file is not writable + if (auto E = tryCreateFile(Config->PrintSymbolOrder)) + error("cannot open symbol order output file " + Config->PrintSymbolOrder + ": " + E.message()); if (errorCount()) return; diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -274,6 +274,9 @@ "List identical folded sections", "Do not list identical folded sections (default)">; +defm print_symbol_order: + Eq<"print-symbol-order", "Print symbols ordered by --call-graph-orderfile into .">; + 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 --- /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 --- /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 + + +