[llvm] 6693c56 - [llvm-profgen] Support to load debug info from a second binary
Hongtao Yu via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 24 17:14:13 PST 2022
Author: wlei
Date: 2022-01-24T17:14:05-08:00
New Revision: 6693c562f90925dd5214d86875a6f82ca5c6ef93
URL: https://github.com/llvm/llvm-project/commit/6693c562f90925dd5214d86875a6f82ca5c6ef93
DIFF: https://github.com/llvm/llvm-project/commit/6693c562f90925dd5214d86875a6f82ca5c6ef93.diff
LOG: [llvm-profgen] Support to load debug info from a second binary
For reducing binary size purpose, the binary's debug info and executable segment can be separated(like using objcopy --only-keep-debug). Here add support in llvm-profgen to use two binaries as input. The original one is executable binary and added for debug info only binary. Adding a flag `--debug-binary=file-path`, with this, the binary will load debug info from debug binary.
Reviewed By: hoy, wenlei
Differential Revision: https://reviews.llvm.org/D115948
Added:
llvm/test/tools/llvm-profgen/separate-debuginfo-binary.test
Modified:
llvm/tools/llvm-profgen/ProfiledBinary.cpp
llvm/tools/llvm-profgen/ProfiledBinary.h
llvm/tools/llvm-profgen/llvm-profgen.cpp
Removed:
################################################################################
diff --git a/llvm/test/tools/llvm-profgen/separate-debuginfo-binary.test b/llvm/test/tools/llvm-profgen/separate-debuginfo-binary.test
new file mode 100644
index 0000000000000..3daeac33471ce
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/separate-debuginfo-binary.test
@@ -0,0 +1,57 @@
+; RUN: llvm-objcopy --strip-debug %S/Inputs/inline-noprobe.perfbin %t1
+; RUN: llvm-objcopy --only-keep-debug %S/Inputs/inline-noprobe.perfbin %t2
+; RUN: echo -e "0\n0" > %t
+; RUN: llvm-profgen --format=text --unsymbolized-profile=%t --binary=%t1 --debug-binary=%t2 --output=%t3 --fill-zero-for-all-funcs
+; RUN: FileCheck %s --input-file %t3 --check-prefix=CHECK
+
+; RUN: llvm-objcopy --strip-debug %S/Inputs/inline-cs-pseudoprobe.perfbin %t4
+; RUN: llvm-objcopy --only-keep-debug %S/Inputs/inline-cs-pseudoprobe.perfbin %t5
+; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-pseudoprobe.perfscript --binary=%t4 --debug-binary=%t5 --output=%t6 --profile-summary-hot-count=0 --csspgo-preinliner=0
+; RUN: FileCheck %s --input-file %t6 --check-prefix=CHECK-CS-PROBE
+
+; CHECK: bar:0:0
+; CHECK: 1: 0
+; CHECK: 5: 0
+; CHECK: foo:0:0
+; CHECK: 0: 0
+; CHECK: 2.1: 0
+; CHECK: 3: 0
+; CHECK: 3.2: 0
+; CHECK: 4: 0
+; CHECK: 3.1: bar:0
+; CHECK: 1: 0
+; CHECK: 65533: 0
+; CHECK: 3.2: bar:0
+; CHECK: 1: 0
+; CHECK: 7: 0
+; CHECK: main:0:0
+; CHECK: 0: 0
+; CHECK: 2: 0
+; CHECK: 1: foo:0
+; CHECK: 2.1: 0
+; CHECK: 3: 0
+; CHECK: 3.2: 0
+; CHECK: 4: 0
+; CHECK: 65526: 0
+; CHECK: 3.1: bar:0
+; CHECK: 1: 0
+; CHECK: 65533: 0
+; CHECK: 3.2: bar:0
+; CHECK: 1: 0
+
+
+; CHECK-CS-PROBE: [main:2 @ foo]:74:0
+; CHECK-CS-PROBE: 1: 0
+; CHECK-CS-PROBE: 2: 15
+; CHECK-CS-PROBE: 3: 15
+; CHECK-CS-PROBE: 4: 14
+; CHECK-CS-PROBE: 5: 1
+; CHECK-CS-PROBE: 6: 15
+; CHECK-CS-PROBE: 7: 0
+; CHECK-CS-PROBE: 8: 14 bar:14
+; CHECK-CS-PROBE: 9: 0
+; CHECK-CS-PROBE: !CFGChecksum: 563088904013236
+; CHECK-CS-PROBE: [main:2 @ foo:8 @ bar]:28:14
+; CHECK-CS-PROBE: 1: 14
+; CHECK-CS-PROBE: 4: 14
+; CHECK-CS-PROBE: !CFGChecksum: 72617220756
diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
index 6dc0d2604367d..a773a3c98d409 100644
--- a/llvm/tools/llvm-profgen/ProfiledBinary.cpp
+++ b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
@@ -187,9 +187,9 @@ void ProfiledBinary::warnNoFuncEntry() {
void ProfiledBinary::load() {
// Attempt to open the binary.
OwningBinary<Binary> OBinary = unwrapOrError(createBinary(Path), Path);
- Binary &Binary = *OBinary.getBinary();
+ Binary &ExeBinary = *OBinary.getBinary();
- auto *Obj = dyn_cast<ELFObjectFileBase>(&Binary);
+ auto *Obj = dyn_cast<ELFObjectFileBase>(&ExeBinary);
if (!Obj)
exitWithError("not a valid Elf image", Path);
@@ -206,7 +206,15 @@ void ProfiledBinary::load() {
decodePseudoProbe(Obj);
// Load debug info of subprograms from DWARF section.
- loadSymbolsFromDWARF(*cast<ObjectFile>(&Binary));
+ // If path of debug info binary is specified, use the debug info from it,
+ // otherwise use the debug info from the executable binary.
+ if (!DebugBinaryPath.empty()) {
+ OwningBinary<Binary> DebugPath =
+ unwrapOrError(createBinary(DebugBinaryPath), DebugBinaryPath);
+ loadSymbolsFromDWARF(*dyn_cast<ObjectFile>(DebugPath.getBinary()));
+ } else {
+ loadSymbolsFromDWARF(*dyn_cast<ObjectFile>(&ExeBinary));
+ }
// Disassemble the text sections.
disassemble(Obj);
@@ -684,8 +692,9 @@ SampleContextFrameVector ProfiledBinary::symbolize(const InstructionPointer &IP,
"Binary should only symbolize its own instruction");
auto Addr = object::SectionedAddress{IP.Offset + getPreferredBaseAddress(),
object::SectionedAddress::UndefSection};
- DIInliningInfo InlineStack =
- unwrapOrError(Symbolizer->symbolizeInlinedCode(Path, Addr), getName());
+ DIInliningInfo InlineStack = unwrapOrError(
+ Symbolizer->symbolizeInlinedCode(SymbolizerPath.str(), Addr),
+ SymbolizerPath);
SampleContextFrameVector CallStack;
for (int32_t I = InlineStack.getNumberOfFrames() - 1; I >= 0; I--) {
diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.h b/llvm/tools/llvm-profgen/ProfiledBinary.h
index b5c985fe6ebbc..d3d1c6f1fd248 100644
--- a/llvm/tools/llvm-profgen/ProfiledBinary.h
+++ b/llvm/tools/llvm-profgen/ProfiledBinary.h
@@ -185,8 +185,12 @@ class BinarySizeContextTracker {
using OffsetRange = std::pair<uint64_t, uint64_t>;
class ProfiledBinary {
- // Absolute path of the binary.
+ // Absolute path of the executable binary.
std::string Path;
+ // Path of the debug info binary.
+ std::string DebugBinaryPath;
+ // Path of symbolizer path which should be pointed to binary with debug info.
+ StringRef SymbolizerPath;
// The target triple.
Triple TheTriple;
// The runtime base address that the first executable segment is loaded at.
@@ -311,10 +315,12 @@ class ProfiledBinary {
void load();
public:
- ProfiledBinary(const StringRef Path)
- : Path(Path), ProEpilogTracker(this),
+ ProfiledBinary(const StringRef ExeBinPath, const StringRef DebugBinPath)
+ : Path(ExeBinPath), DebugBinaryPath(DebugBinPath), ProEpilogTracker(this),
TrackFuncContextSize(EnableCSPreInliner &&
UseContextCostForPreInliner) {
+ // Point to executable binary if debug info binary is not specified.
+ SymbolizerPath = DebugBinPath.empty() ? ExeBinPath : DebugBinPath;
setupSymbolizer();
load();
}
diff --git a/llvm/tools/llvm-profgen/llvm-profgen.cpp b/llvm/tools/llvm-profgen/llvm-profgen.cpp
index 0ab93ca0bd65b..f092df04d52b3 100644
--- a/llvm/tools/llvm-profgen/llvm-profgen.cpp
+++ b/llvm/tools/llvm-profgen/llvm-profgen.cpp
@@ -48,9 +48,15 @@ static cl::opt<std::string> UnsymbolizedProfFilename(
static cl::alias UPA("up", cl::desc("Alias for --unsymbolized-profile"),
cl::aliasopt(UnsymbolizedProfFilename));
-static cl::opt<std::string> BinaryPath(
- "binary", cl::value_desc("binary"), cl::Required,
- cl::desc("Path of profiled binary, only one binary is supported."),
+static cl::opt<std::string>
+ BinaryPath("binary", cl::value_desc("binary"), cl::Required,
+ cl::desc("Path of profiled executable binary."),
+ cl::cat(ProfGenCategory));
+
+static cl::opt<std::string> DebugBinPath(
+ "debug-binary", cl::value_desc("debug-binary"), cl::ZeroOrMore,
+ cl::desc("Path of debug info binary, llvm-profgen will load the DWARF info "
+ "from it instead of the executable binary."),
cl::cat(ProfGenCategory));
extern cl::opt<bool> ShowDisassemblyOnly;
@@ -135,7 +141,7 @@ int main(int argc, const char *argv[]) {
// Load symbols and disassemble the code of a given binary.
std::unique_ptr<ProfiledBinary> Binary =
- std::make_unique<ProfiledBinary>(BinaryPath);
+ std::make_unique<ProfiledBinary>(BinaryPath, DebugBinPath);
if (ShowDisassemblyOnly)
return EXIT_SUCCESS;
More information about the llvm-commits
mailing list