diff --git a/llvm/tools/llvm-profgen/PerfReader.h b/llvm/tools/llvm-profgen/PerfReader.h --- a/llvm/tools/llvm-profgen/PerfReader.h +++ b/llvm/tools/llvm-profgen/PerfReader.h @@ -13,6 +13,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Regex.h" +#include #include #include #include @@ -530,8 +531,8 @@ Binary->setBaseAddress(Binary->getPreferredBaseAddress()); }; virtual ~PerfReaderBase() = default; - static std::unique_ptr create(ProfiledBinary *Binary, - PerfInputFile &PerfInput); + static std::unique_ptr + create(ProfiledBinary *Binary, PerfInputFile &PerfInput, uint32_t PIDFilter); // Entry of the reader to parse multiple perf traces virtual void parsePerfTraces() = 0; @@ -555,14 +556,15 @@ // Read perf script to parse the events and samples. class PerfScriptReader : public PerfReaderBase { public: - PerfScriptReader(ProfiledBinary *B, StringRef PerfTrace) - : PerfReaderBase(B, PerfTrace){}; + PerfScriptReader(ProfiledBinary *B, StringRef PerfTrace, uint32_t PID) + : PerfReaderBase(B, PerfTrace), PIDFilter(PID){}; // Entry of the reader to parse multiple perf traces virtual void parsePerfTraces() override; // Generate perf script from perf data static PerfInputFile convertPerfDataToTrace(ProfiledBinary *Binary, - PerfInputFile &File); + PerfInputFile &File, + uint32_t PIDFilter); // Extract perf script type by peaking at the input static PerfContent checkPerfScriptType(StringRef FileName); @@ -622,6 +624,8 @@ AggregatedCounter AggregatedSamples; // Keep track of all invalid return addresses std::set InvalidReturnAddresses; + // PID for the process of interest + uint32_t PIDFilter; }; /* @@ -632,8 +636,8 @@ */ class LBRPerfReader : public PerfScriptReader { public: - LBRPerfReader(ProfiledBinary *Binary, StringRef PerfTrace) - : PerfScriptReader(Binary, PerfTrace){}; + LBRPerfReader(ProfiledBinary *Binary, StringRef PerfTrace, uint32_t PID) + : PerfScriptReader(Binary, PerfTrace, PID){}; // Parse the LBR only sample. virtual void parseSample(TraceStream &TraceIt, uint64_t Count) override; }; @@ -649,8 +653,8 @@ */ class HybridPerfReader : public PerfScriptReader { public: - HybridPerfReader(ProfiledBinary *Binary, StringRef PerfTrace) - : PerfScriptReader(Binary, PerfTrace){}; + HybridPerfReader(ProfiledBinary *Binary, StringRef PerfTrace, uint32_t PID) + : PerfScriptReader(Binary, PerfTrace, PID){}; // Parse the hybrid sample including the call and LBR line void parseSample(TraceStream &TraceIt, uint64_t Count) override; void generateUnsymbolizedProfile() override; diff --git a/llvm/tools/llvm-profgen/PerfReader.cpp b/llvm/tools/llvm-profgen/PerfReader.cpp --- a/llvm/tools/llvm-profgen/PerfReader.cpp +++ b/llvm/tools/llvm-profgen/PerfReader.cpp @@ -326,8 +326,9 @@ return true; } -std::unique_ptr -PerfReaderBase::create(ProfiledBinary *Binary, PerfInputFile &PerfInput) { +std::unique_ptr PerfReaderBase::create(ProfiledBinary *Binary, + PerfInputFile &PerfInput, + uint32_t PIDFilter) { std::unique_ptr PerfReader; if (PerfInput.Format == PerfFormat::UnsymbolizedProfile) { @@ -338,7 +339,8 @@ // For perf data input, we need to convert them into perf script first. if (PerfInput.Format == PerfFormat::PerfData) - PerfInput = PerfScriptReader::convertPerfDataToTrace(Binary, PerfInput); + PerfInput = + PerfScriptReader::convertPerfDataToTrace(Binary, PerfInput, PIDFilter); assert((PerfInput.Format == PerfFormat::PerfScript) && "Should be a perfscript!"); @@ -346,9 +348,10 @@ PerfInput.Content = PerfScriptReader::checkPerfScriptType(PerfInput.InputFile); if (PerfInput.Content == PerfContent::LBRStack) { - PerfReader.reset(new HybridPerfReader(Binary, PerfInput.InputFile)); + PerfReader.reset( + new HybridPerfReader(Binary, PerfInput.InputFile, PIDFilter)); } else if (PerfInput.Content == PerfContent::LBR) { - PerfReader.reset(new LBRPerfReader(Binary, PerfInput.InputFile)); + PerfReader.reset(new LBRPerfReader(Binary, PerfInput.InputFile, PIDFilter)); } else { exitWithError("Unsupported perfscript!"); } @@ -357,7 +360,8 @@ } PerfInputFile PerfScriptReader::convertPerfDataToTrace(ProfiledBinary *Binary, - PerfInputFile &File) { + PerfInputFile &File, + uint32_t PIDFilter) { StringRef PerfData = File.InputFile; // Run perf script to retrieve PIDs matching binary we're interested in. auto PerfExecutable = sys::Process::FindInEnvPath("PATH", "perf"); @@ -383,7 +387,7 @@ if (isMMap2Event(TraceIt.getCurrentLine()) && extractMMap2EventForBinary(Binary, TraceIt.getCurrentLine(), MMap)) { auto It = PIDSet.emplace(MMap.PID); - if (It.second) { + if (It.second && (!PIDFilter || MMap.PID == PIDFilter)) { if (!PIDs.empty()) { PIDs.append(","); } @@ -412,6 +416,10 @@ if (Binary->getName() != BinaryName) return; + // Drop the event if process does not match pid filter + if (PIDFilter && Event.PID != PIDFilter) + return; + // Drop the event if its image is loaded at the same address if (Event.Address == Binary->getBaseAddress()) { Binary->setIsLoadedByMMap(true); diff --git a/llvm/tools/llvm-profgen/llvm-profgen.cpp b/llvm/tools/llvm-profgen/llvm-profgen.cpp --- a/llvm/tools/llvm-profgen/llvm-profgen.cpp +++ b/llvm/tools/llvm-profgen/llvm-profgen.cpp @@ -54,6 +54,11 @@ cl::desc("Path of profiled executable binary."), cl::cat(ProfGenCategory)); +static cl::opt + ProcessId("pid", cl::value_desc("process Id"), cl::ZeroOrMore, cl::init(0), + cl::desc("Process Id for the profiled executable binary."), + cl::cat(ProfGenCategory)); + static cl::opt DebugBinPath( "debug-binary", cl::value_desc("debug-binary"), cl::ZeroOrMore, cl::desc("Path of debug info binary, llvm-profgen will load the DWARF info " @@ -148,7 +153,7 @@ PerfInputFile PerfFile = getPerfInputFile(); std::unique_ptr Reader = - PerfReaderBase::create(Binary.get(), PerfFile); + PerfReaderBase::create(Binary.get(), PerfFile, ProcessId); // Parse perf events and samples Reader->parsePerfTraces();