Change to use unique pointer of profiled binary to unblock asan.
At same time, I realized we can decouple to move the profiled binary loading out of PerfReader, so I made some other related refactors.
Reviewed By: hoy
Differential Revision: https://reviews.llvm.org/D108254
//===----------------------------------------------------------------------===//
#include "PerfReader.h"
#include "ProfileGenerator.h"
-#include "llvm/Support/FileSystem.h"
static cl::opt<bool> ShowMmapEvents("show-mmap-events", cl::ReallyHidden,
cl::init(false), cl::ZeroOrMore,
return true;
}
-void PerfReaderBase::validateCommandLine(
- StringRef BinaryPath, cl::list<std::string> &PerfTraceFilenames) {
- // Allow the invalid perfscript if we only use to show binary disassembly
- if (!ShowDisassemblyOnly) {
- for (auto &File : PerfTraceFilenames) {
- if (!llvm::sys::fs::exists(File)) {
- std::string Msg = "Input perf script(" + File + ") doesn't exist!";
- exitWithError(Msg);
- }
- }
- }
-
- if (!llvm::sys::fs::exists(BinaryPath)) {
- std::string Msg = "Input binary(" + BinaryPath.str() + ") doesn't exist!";
- exitWithError(Msg);
- }
-
- if (CSProfileGenerator::MaxCompressionSize < -1) {
- exitWithError("Value of --compress-recursion should >= -1");
- }
- if (ShowSourceLocations && !ShowDisassemblyOnly) {
- exitWithError("--show-source-locations should work together with "
- "--show-disassembly-only!");
- }
-}
-
std::unique_ptr<PerfReaderBase>
-PerfReaderBase::create(StringRef BinaryPath,
+PerfReaderBase::create(ProfiledBinary *Binary,
cl::list<std::string> &PerfTraceFilenames) {
- validateCommandLine(BinaryPath, PerfTraceFilenames);
-
PerfScriptType PerfType = extractPerfType(PerfTraceFilenames);
std::unique_ptr<PerfReaderBase> PerfReader;
if (PerfType == PERF_LBR_STACK) {
- PerfReader.reset(new HybridPerfReader(BinaryPath));
+ PerfReader.reset(new HybridPerfReader(Binary));
} else if (PerfType == PERF_LBR) {
// TODO:
exitWithError("Unsupported perfscript!");
return PerfReader;
}
-PerfReaderBase::PerfReaderBase(StringRef BinaryPath) {
- // Load the binary.
- loadBinary(BinaryPath);
-}
-
-void PerfReaderBase::loadBinary(const StringRef BinaryPath) {
- // Call to load the binary in the ctor of ProfiledBinary.
- Binary = new ProfiledBinary(BinaryPath);
- // Initialize the base address to preferred address.
- Binary->setBaseAddress(Binary->getPreferredBaseAddress());
-}
-
void PerfReaderBase::updateBinaryAddress(const MMapEvent &Event) {
// Drop the event which doesn't belong to user-provided binary
StringRef BinaryName = llvm::sys::path::filename(Event.BinaryPath);
"IP should align with context leaf");
}
- const ProfiledBinary *getBinary() const { return Binary; }
bool hasNextLBR() const { return LBRIndex < LBRStack.size(); }
uint64_t getCurrentLBRSource() const { return LBRStack[LBRIndex].Source; }
uint64_t getCurrentLBRTarget() const { return LBRStack[LBRIndex].Target; }
const ProfiledBinary *Binary;
};
-// Load binaries and read perf trace to parse the events and samples
+// Read perf trace to parse the events and samples.
class PerfReaderBase {
public:
- PerfReaderBase(StringRef BinaryPath);
+ PerfReaderBase(ProfiledBinary *B) : Binary(B) {
+ // Initialize the base address to preferred address.
+ Binary->setBaseAddress(Binary->getPreferredBaseAddress());
+ };
virtual ~PerfReaderBase() = default;
static std::unique_ptr<PerfReaderBase>
- create(StringRef BinaryPath, cl::list<std::string> &PerfTraceFilenames);
+ create(ProfiledBinary *Binary, cl::list<std::string> &PerfTraceFilenames);
// A LBR sample is like:
// 0x5c6313f/0x5c63170/P/-/-/0 0x5c630e7/0x5c63130/P/-/-/0 ...
StringRef BinaryPath;
};
- /// Load symbols and disassemble the code of a given binary.
- void loadBinary(const StringRef BinaryPath);
void updateBinaryAddress(const MMapEvent &Event);
- ProfiledBinary *getBinary() const { return Binary; }
PerfScriptType getPerfScriptType() const { return PerfType; }
// Entry of the reader to parse multiple perf traces
void parsePerfTraces(cl::list<std::string> &PerfTraceFilenames);
}
protected:
- /// Validate the command line input
- static void validateCommandLine(StringRef BinaryPath,
- cl::list<std::string> &PerfTraceFilenames);
static PerfScriptType
extractPerfType(cl::list<std::string> &PerfTraceFilenames);
/// Parse a single line of a PERF_RECORD_MMAP2 event looking for a
*/
class HybridPerfReader : public PerfReaderBase {
public:
- HybridPerfReader(StringRef BinaryPath) : PerfReaderBase(BinaryPath) {
+ HybridPerfReader(ProfiledBinary *Binary) : PerfReaderBase(Binary) {
PerfType = PERF_LBR_STACK;
};
// Parse the hybrid sample including the call and LBR line
#include "ProfileGenerator.h"
#include "ProfiledBinary.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/TargetSelect.h"
cl::cat(ProfGenCategory));
extern cl::opt<bool> ShowDisassemblyOnly;
+extern cl::opt<bool> ShowSourceLocations;
using namespace llvm;
using namespace sampleprof;
+// Validate the command line input.
+static void validateCommandLine(StringRef BinaryPath,
+ cl::list<std::string> &PerfTraceFilenames) {
+ // Allow the invalid perfscript if we only use to show binary disassembly.
+ if (!ShowDisassemblyOnly) {
+ for (auto &File : PerfTraceFilenames) {
+ if (!llvm::sys::fs::exists(File)) {
+ std::string Msg = "Input perf script(" + File + ") doesn't exist!";
+ exitWithError(Msg);
+ }
+ }
+ }
+
+ if (!llvm::sys::fs::exists(BinaryPath)) {
+ std::string Msg = "Input binary(" + BinaryPath.str() + ") doesn't exist!";
+ exitWithError(Msg);
+ }
+
+ if (CSProfileGenerator::MaxCompressionSize < -1) {
+ exitWithError("Value of --compress-recursion should >= -1");
+ }
+ if (ShowSourceLocations && !ShowDisassemblyOnly) {
+ exitWithError("--show-source-locations should work together with "
+ "--show-disassembly-only!");
+ }
+}
+
int main(int argc, const char *argv[]) {
InitLLVM X(argc, argv);
cl::HideUnrelatedOptions({&ProfGenCategory, &getColorCategory()});
cl::ParseCommandLineOptions(argc, argv, "llvm SPGO profile generator\n");
+ validateCommandLine(BinaryPath, PerfTraceFilenames);
- if (ShowDisassemblyOnly) {
- (void)ProfiledBinary(BinaryPath);
+ // Load symbols and disassemble the code of a given binary.
+ std::unique_ptr<ProfiledBinary> Binary =
+ std::make_unique<ProfiledBinary>(BinaryPath);
+ if (ShowDisassemblyOnly)
return EXIT_SUCCESS;
- }
- // Load binaries and parse perf events and samples
+ // Parse perf events and samples
std::unique_ptr<PerfReaderBase> Reader =
- PerfReaderBase::create(BinaryPath, PerfTraceFilenames);
+ PerfReaderBase::create(Binary.get(), PerfTraceFilenames);
Reader->parsePerfTraces(PerfTraceFilenames);
- std::unique_ptr<ProfileGenerator> Generator =
- ProfileGenerator::create(Reader->getBinary(), Reader->getSampleCounters(),
- Reader->getPerfScriptType());
+ std::unique_ptr<ProfileGenerator> Generator = ProfileGenerator::create(
+ Binary.get(), Reader->getSampleCounters(), Reader->getPerfScriptType());
Generator->generateProfile();
Generator->write();