diff --git a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-debuginfod.c b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-debuginfod.c new file mode 100644 index 0000000000000..788cb31e5116c --- /dev/null +++ b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-debuginfod.c @@ -0,0 +1,24 @@ +// REQUIRES: curl +// RUN: rm -rf %t + +// Default instrumented build with no profile correlation. +// RUN: %clang_pgogen -o %t.default -Wl,--build-id=0x12345678 -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t.default +// RUN: llvm-profdata merge -o %t.default.profdata %t.profraw + +// Build with profile debuginfo correlation. +// RUN: %clang_pgogen -o %t.correlate.exe -Wl,--build-id=0x12345678 -g -gdwarf-4 -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp +// RUN: env LLVM_PROFILE_FILE=%t.debug-info-correlate.proflite %run %t.correlate.exe + +// Test llvm-profdata merge profile correlation with --debuginfod option. +// RUN: mkdir -p %t/buildid/12345678 +// RUN: cp %t.correlate.exe %t/buildid/12345678/debuginfo +// RUN: mkdir -p %t/debuginfod-cache +// RUN: env DEBUGINFOD_CACHE_PATH=%t/debuginfod-cache DEBUGINFOD_URLS=file://%t llvm-profdata merge -o %t.correlate-debuginfod.profdata --debuginfod --correlate=debug-info %t.debug-info-correlate.proflite +// RUN: diff <(llvm-profdata show --all-functions --counts %t.default.profdata) <(llvm-profdata show --all-functions --counts %t.correlate-debuginfod.profdata) + +// Test llvm-profdata merge profile correlation with --debug-file-directory option. +// RUN: mkdir -p %t/.build-id/12 +// RUN: cp %t.correlate.exe %t/.build-id/12/345678.debug +// RUN: llvm-profdata merge -o %t.correlate-debug-file-dir.profdata --debug-file-directory %t --correlate=debug-info %t.debug-info-correlate.proflite +// RUN: diff <(llvm-profdata show --all-functions --counts %t.default.profdata) <(llvm-profdata show --all-functions --counts %t.correlate-debug-file-dir.profdata) diff --git a/compiler-rt/test/profile/instrprof-binary-correlate-debuginfod.c b/compiler-rt/test/profile/instrprof-binary-correlate-debuginfod.c new file mode 100644 index 0000000000000..09fb39cc3d076 --- /dev/null +++ b/compiler-rt/test/profile/instrprof-binary-correlate-debuginfod.c @@ -0,0 +1,41 @@ +// REQUIRES: linux || windows +// REQUIRES: curl + +// Default instrumented build with no profile correlation. +// RUN: %clang_profgen -o %t.default.exe -Wl,--build-id=0x12345678 -fprofile-instr-generate -fcoverage-mapping %S/Inputs/instrprof-debug-info-correlate-main.cpp %S/Inputs/instrprof-debug-info-correlate-foo.cpp +// RUN: env LLVM_PROFILE_FILE=%t.default.profraw %run %t.default.exe +// RUN: llvm-profdata merge -o %t.default.profdata %t.default.profraw +// RUN: llvm-profdata show --all-functions --counts %t.default.profdata > %t.default.profdata.show + +// Build with profile binary correlation. +// RUN: %clang_profgen -o %t.correlate.exe -Wl,--build-id=0x12345678 -fprofile-instr-generate -fcoverage-mapping -mllvm -profile-correlate=binary %S/Inputs/instrprof-debug-info-correlate-main.cpp %S/Inputs/instrprof-debug-info-correlate-foo.cpp +// Strip above binary and run +// RUN: llvm-strip %t.correlate.exe -o %t.stripped.exe +// RUN: env LLVM_PROFILE_FILE=%t.correlate.profraw %run %t.stripped.exe + +// Test llvm-profdata merge profile correlation with --debuginfod option. +// RUN: mkdir -p %t/buildid/12345678 +// RUN: cp %t.correlate.exe %t/buildid/12345678/debuginfo +// RUN: mkdir -p %t/debuginfod-cache +// RUN: env DEBUGINFOD_CACHE_PATH=%t/debuginfod-cache DEBUGINFOD_URLS=file://%t llvm-profdata merge -o %t.correlate-debuginfod.profdata --debuginfod --correlate=binary %t.correlate.profraw +// RUN: llvm-profdata show --all-functions --counts %t.correlate-debuginfod.profdata > %t.correlate-debuginfod.profdata.show +// RUN: diff %t.default.profdata.show %t.correlate-debuginfod.profdata.show + +// Test llvm-profdata merge profile correlation with --debug-file-directory option. +// RUN: mkdir -p %t/.build-id/12 +// RUN: cp %t.correlate.exe %t/.build-id/12/345678.debug +// RUN: llvm-profdata merge -o %t.correlate-debug-file-dir.profdata --debug-file-directory %t --correlate=binary %t.correlate.profraw +// RUN: llvm-profdata show --all-functions --counts %t.correlate-debug-file-dir.profdata > %t.correlate-debug-file-dir.profdata.show +// RUN: diff %t.default.profdata.show %t.correlate-debug-file-dir.profdata.show + +// Test error for llvm-profdata merge profile correlation with only --correlate=binary option. +// RUN: not llvm-profdata merge -o %t.correlate-error.profdata --correlate=binary %t.correlate.profraw 2>&1 | FileCheck %s --check-prefix=MISSING-FLAG +// MISSING-FLAG: error: Expected --debuginfod or --debug-file-directory when --correlate is provided + +// Test error for llvm-profdata merge profile correlation when a proper --correlate option is not provided. +// RUN: not llvm-profdata merge -o %t.correlate-error.profdata --debug-file-directory %t --correlate="" %t.correlate.profraw 2>&1 | FileCheck %s --check-prefix=MISSING-CORRELATION-KIND +// MISSING-CORRELATION-KIND: error: Expected --correlate when --debug-file-directory is provided + +// Test error for llvm-profdata merge profile correlation with mixing correlation options. +// RUN: not llvm-profdata merge -o %t.error.profdata --binary-file=%t.correlate.exe --debug-file-directory %t --correlate=binary %t.correlate.profraw 2>&1 | FileCheck %s --check-prefix=MIXING-FLAGS +// MIXING-FLAGS: error: Expected only one of -binary-file, -debuginfod or -debug-file-directory diff --git a/compiler-rt/test/profile/lit.cfg.py b/compiler-rt/test/profile/lit.cfg.py index d3ba115731c5d..3b3019a07c30a 100644 --- a/compiler-rt/test/profile/lit.cfg.py +++ b/compiler-rt/test/profile/lit.cfg.py @@ -179,3 +179,6 @@ def exclude_unsupported_files_for_aix(dirname): if config.android: config.unsupported = True + +if config.have_curl: + config.available_features.add("curl") diff --git a/llvm/docs/CommandGuide/llvm-profdata.rst b/llvm/docs/CommandGuide/llvm-profdata.rst index acf016a6dbcd7..610148840fca9 100644 --- a/llvm/docs/CommandGuide/llvm-profdata.rst +++ b/llvm/docs/CommandGuide/llvm-profdata.rst @@ -204,6 +204,25 @@ OPTIONS the raw profile. When ``-profile-correlate=binary`` was used for instrumentation, use this option to correlate the raw profile. +.. option:: --debuginfod + + Use debuginfod to find the associated executables that contain profile data and + name sections for the raw profiles to correlate them. + When -profile-correlate=binary was used for instrumentation, this option can be + used for correlation. + +.. option:: --debug-file-directory= + + Use provided local directories to search for executables that contain profile + data and name sections for the raw profiles to correlate them. + When -profile-correlate=binary was used for instrumentation, this option can be + used for correlation. + +.. option:: --correlate= + + Specify the correlation kind (debug_info or binary) to use when -debuginfod or + -debug-file-directory= option is provided. + .. option:: --temporal-profile-trace-reservoir-size The maximum number of temporal profile traces to be stored in the output diff --git a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h index c07c67d287e2c..c873597e42095 100644 --- a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h +++ b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h @@ -13,6 +13,8 @@ #define LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H #include "llvm/ADT/DenseSet.h" +#include "llvm/Debuginfod/BuildIDFetcher.h" +#include "llvm/Object/BuildID.h" #include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" @@ -36,7 +38,9 @@ class InstrProfCorrelator { enum ProfCorrelatorKind { NONE, DEBUG_INFO, BINARY }; static llvm::Expected> - get(StringRef Filename, ProfCorrelatorKind FileKind); + get(StringRef Filename, ProfCorrelatorKind FileKind, + const object::BuildIDFetcher *BIDFetcher = nullptr, + const ArrayRef BIs = std::nullopt); /// Construct a ProfileData vector used to correlate raw instrumentation data /// to their functions. diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h index 3b307d0835998..00b361f4ad1c5 100644 --- a/llvm/include/llvm/ProfileData/InstrProfReader.h +++ b/llvm/include/llvm/ProfileData/InstrProfReader.h @@ -197,15 +197,21 @@ class InstrProfReader { /// Factory method to create an appropriately typed reader for the given /// instrprof file. - static Expected> - create(const Twine &Path, vfs::FileSystem &FS, - const InstrProfCorrelator *Correlator = nullptr, - std::function Warn = nullptr); - - static Expected> - create(std::unique_ptr Buffer, - const InstrProfCorrelator *Correlator = nullptr, - std::function Warn = nullptr); + static Expected> create( + const Twine &Path, vfs::FileSystem &FS, + const InstrProfCorrelator *Correlator = nullptr, + const object::BuildIDFetcher *BIDFetcher = nullptr, + const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind = + InstrProfCorrelator::ProfCorrelatorKind::NONE, + std::function Warn = nullptr); + + static Expected> create( + std::unique_ptr Buffer, + const InstrProfCorrelator *Correlator = nullptr, + const object::BuildIDFetcher *BIDFetcher = nullptr, + const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind = + InstrProfCorrelator::ProfCorrelatorKind::NONE, + std::function Warn = nullptr); /// \param Weight for raw profiles use this as the temporal profile trace /// weight @@ -314,6 +320,14 @@ class RawInstrProfReader : public InstrProfReader { /// If available, this hold the ProfileData array used to correlate raw /// instrumentation data to their functions. const InstrProfCorrelatorImpl *Correlator; + /// Fetches debuginfo by build id to correlate profiles. + const object::BuildIDFetcher *BIDFetcher; + /// Correlates profiles with build id fetcher by fetching debuginfo with build + /// ID. + std::unique_ptr BIDFetcherCorrelator; + /// Indicates if should use debuginfo or binary to correlate with build id + /// fetcher. + InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind; /// A list of timestamps paired with a function name reference. std::vector> TemporalProfTimestamps; bool ShouldSwapBytes; @@ -349,13 +363,18 @@ class RawInstrProfReader : public InstrProfReader { static const uint64_t MaxCounterValue = (1ULL << 56); public: - RawInstrProfReader(std::unique_ptr DataBuffer, - const InstrProfCorrelator *Correlator, - std::function Warn) + RawInstrProfReader( + std::unique_ptr DataBuffer, + const InstrProfCorrelator *Correlator, + const object::BuildIDFetcher *BIDFetcher, + const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind, + std::function Warn) : DataBuffer(std::move(DataBuffer)), Correlator(dyn_cast_or_null>( Correlator)), - Warn(Warn) {} + BIDFetcher(BIDFetcher), + BIDFetcherCorrelatorKind(BIDFetcherCorrelatorKind), Warn(Warn) {} + RawInstrProfReader(const RawInstrProfReader &) = delete; RawInstrProfReader &operator=(const RawInstrProfReader &) = delete; @@ -439,7 +458,7 @@ class RawInstrProfReader : public InstrProfReader { void advanceData() { // `CountersDelta` is a constant zero when using debug info correlation. - if (!Correlator) { + if (!Correlator && !BIDFetcherCorrelator) { // The initial CountersDelta is the in-memory address difference between // the data and counts sections: // start(__llvm_prf_cnts) - start(__llvm_prf_data) diff --git a/llvm/lib/ProfileData/InstrProfCorrelator.cpp b/llvm/lib/ProfileData/InstrProfCorrelator.cpp index 44e2aeb00d8cc..d92107f93dc56 100644 --- a/llvm/lib/ProfileData/InstrProfCorrelator.cpp +++ b/llvm/lib/ProfileData/InstrProfCorrelator.cpp @@ -91,7 +91,31 @@ InstrProfCorrelator::Context::get(std::unique_ptr Buffer, } llvm::Expected> -InstrProfCorrelator::get(StringRef Filename, ProfCorrelatorKind FileKind) { +InstrProfCorrelator::get(StringRef Filename, ProfCorrelatorKind FileKind, + const object::BuildIDFetcher *BIDFetcher, + const ArrayRef BIs) { + std::optional Path; + if (BIDFetcher) { + if (BIs.empty()) + return make_error( + instrprof_error::unable_to_correlate_profile, + "unsupported profile binary correlation when there is no build ID " + "in a profile"); + if (BIs.size() > 1) + return make_error( + instrprof_error::unable_to_correlate_profile, + "unsupported profile binary correlation when there are multiple " + "build IDs in a profile"); + + Path = BIDFetcher->fetch(BIs.front()); + if (!Path) + return make_error( + instrprof_error::unable_to_correlate_profile, + "Missing build ID: " + llvm::toHex(BIs.front(), + /*LowerCase=*/true)); + Filename = *Path; + } + if (FileKind == DEBUG_INFO) { auto DsymObjectsOrErr = object::MachOObjectFile::findDsymObjectMembers(Filename); diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp index 6d078c58ac805..b90617c74f6d1 100644 --- a/llvm/lib/ProfileData/InstrProfReader.cpp +++ b/llvm/lib/ProfileData/InstrProfReader.cpp @@ -150,22 +150,25 @@ static void printBinaryIdsInternal(raw_ostream &OS, } } -Expected> -InstrProfReader::create(const Twine &Path, vfs::FileSystem &FS, - const InstrProfCorrelator *Correlator, - std::function Warn) { +Expected> InstrProfReader::create( + const Twine &Path, vfs::FileSystem &FS, + const InstrProfCorrelator *Correlator, + const object::BuildIDFetcher *BIDFetcher, + const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind, + std::function Warn) { // Set up the buffer to read. auto BufferOrError = setupMemoryBuffer(Path, FS); if (Error E = BufferOrError.takeError()) return std::move(E); return InstrProfReader::create(std::move(BufferOrError.get()), Correlator, - Warn); + BIDFetcher, BIDFetcherCorrelatorKind, Warn); } -Expected> -InstrProfReader::create(std::unique_ptr Buffer, - const InstrProfCorrelator *Correlator, - std::function Warn) { +Expected> InstrProfReader::create( + std::unique_ptr Buffer, const InstrProfCorrelator *Correlator, + const object::BuildIDFetcher *BIDFetcher, + const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind, + std::function Warn) { if (Buffer->getBufferSize() == 0) return make_error(instrprof_error::empty_raw_profile); @@ -174,9 +177,13 @@ InstrProfReader::create(std::unique_ptr Buffer, if (IndexedInstrProfReader::hasFormat(*Buffer)) Result.reset(new IndexedInstrProfReader(std::move(Buffer))); else if (RawInstrProfReader64::hasFormat(*Buffer)) - Result.reset(new RawInstrProfReader64(std::move(Buffer), Correlator, Warn)); + Result.reset(new RawInstrProfReader64(std::move(Buffer), Correlator, + BIDFetcher, BIDFetcherCorrelatorKind, + Warn)); else if (RawInstrProfReader32::hasFormat(*Buffer)) - Result.reset(new RawInstrProfReader32(std::move(Buffer), Correlator, Warn)); + Result.reset(new RawInstrProfReader32(std::move(Buffer), Correlator, + BIDFetcher, BIDFetcherCorrelatorKind, + Warn)); else if (TextInstrProfReader::hasFormat(*Buffer)) Result.reset(new TextInstrProfReader(std::move(Buffer))); else @@ -633,6 +640,19 @@ Error RawInstrProfReader::readHeader( if (Start + ValueDataOffset > DataBuffer->getBufferEnd()) return error(instrprof_error::bad_header); + if (BIDFetcher) { + std::vector BinaryIDs; + if (Error E = readBinaryIds(BinaryIDs)) + return E; + if (auto E = InstrProfCorrelator::get("", BIDFetcherCorrelatorKind, + BIDFetcher, BinaryIDs) + .moveInto(BIDFetcherCorrelator)) { + return E; + } + if (auto Err = BIDFetcherCorrelator->correlateProfileData(0)) + return Err; + } + if (Correlator) { // These sizes in the raw file are zero because we constructed them in the // Correlator. @@ -643,6 +663,14 @@ Error RawInstrProfReader::readHeader( DataEnd = Data + Correlator->getDataSize(); NamesStart = Correlator->getNamesPointer(); NamesEnd = NamesStart + Correlator->getNamesSize(); + } else if (BIDFetcherCorrelator) { + InstrProfCorrelatorImpl *BIDFetcherCorrelatorImpl = + dyn_cast_or_null>( + BIDFetcherCorrelator.get()); + Data = BIDFetcherCorrelatorImpl->getDataPointer(); + DataEnd = Data + BIDFetcherCorrelatorImpl->getDataSize(); + NamesStart = BIDFetcherCorrelatorImpl->getNamesPointer(); + NamesEnd = NamesStart + BIDFetcherCorrelatorImpl->getNamesSize(); } else { Data = reinterpret_cast *>( Start + DataOffset); diff --git a/llvm/tools/llvm-profdata/CMakeLists.txt b/llvm/tools/llvm-profdata/CMakeLists.txt index 25cf143337ad4..165be9a2ea31b 100644 --- a/llvm/tools/llvm-profdata/CMakeLists.txt +++ b/llvm/tools/llvm-profdata/CMakeLists.txt @@ -12,3 +12,7 @@ add_llvm_tool(llvm-profdata intrinsics_gen GENERATE_DRIVER ) + +if(NOT LLVM_TOOL_LLVM_DRIVER_BUILD) + target_link_libraries(llvm-profdata PRIVATE LLVMDebuginfod) +endif() diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp index 1f6c4c604d57b..fb6a64595622c 100644 --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -13,6 +13,7 @@ #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Debuginfod/HTTPClient.h" #include "llvm/IR/LLVMContext.h" #include "llvm/Object/Binary.h" #include "llvm/ProfileData/InstrProfCorrelator.h" @@ -130,6 +131,23 @@ cl::opt cl::desc("For merge, use the provided unstripped bianry to " "correlate the raw profile."), cl::sub(MergeSubcommand)); +cl::list DebugFileDirectory( + "debug-file-directory", + cl::desc("Directories to search for object files by build ID")); +cl::opt DebugInfod("debuginfod", cl::init(false), cl::Hidden, + cl::sub(MergeSubcommand), + cl::desc("Enable debuginfod")); +cl::opt BIDFetcherProfileCorrelate( + "correlate", + cl::desc("Use debug-info or binary correlation to correlate profiles with " + "build id fetcher"), + cl::init(InstrProfCorrelator::NONE), + cl::values(clEnumValN(InstrProfCorrelator::NONE, "", + "No profile correlation"), + clEnumValN(InstrProfCorrelator::DEBUG_INFO, "debug-info", + "Use debug info to correlate"), + clEnumValN(InstrProfCorrelator::BINARY, "binary", + "Use binary to correlate"))); cl::opt FuncNameFilter( "function", cl::desc("Only functions matching the filter are shown in the output. For " @@ -650,9 +668,11 @@ static void overlapInput(const std::string &BaseFilename, } /// Load an input into a writer context. -static void loadInput(const WeightedFile &Input, SymbolRemapper *Remapper, - const InstrProfCorrelator *Correlator, - const StringRef ProfiledBinary, WriterContext *WC) { +static void +loadInput(const WeightedFile &Input, SymbolRemapper *Remapper, + const InstrProfCorrelator *Correlator, const StringRef ProfiledBinary, + WriterContext *WC, const object::BuildIDFetcher *BIDFetcher = nullptr, + const ProfCorrelatorKind *BIDFetcherCorrelatorKind = nullptr) { std::unique_lock CtxGuard{WC->Lock}; // Copy the filename, because llvm::ThreadPool copied the input "const @@ -730,8 +750,12 @@ static void loadInput(const WeightedFile &Input, SymbolRemapper *Remapper, auto [ErrCode, Msg] = InstrProfError::take(std::move(E)); ReaderWarning = {make_error(ErrCode, Msg), Filename}; }; - auto ReaderOrErr = - InstrProfReader::create(Input.Filename, *FS, Correlator, Warn); + + const ProfCorrelatorKind CorrelatorKind = BIDFetcherCorrelatorKind + ? *BIDFetcherCorrelatorKind + : ProfCorrelatorKind::NONE; + auto ReaderOrErr = InstrProfReader::create(Input.Filename, *FS, Correlator, + BIDFetcher, CorrelatorKind, Warn); if (Error E = ReaderOrErr.takeError()) { // Skip the empty profiles by returning silently. auto [ErrCode, Msg] = InstrProfError::take(std::move(E)); @@ -915,8 +939,15 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs, // TODO: Maybe we should support correlation with mixture of different // correlation modes(w/wo debug-info/object correlation). - if (!DebugInfoFilename.empty() && !BinaryFilename.empty()) - exitWithError("Expected only one of -debug-info, -binary-file"); + if (DebugInfoFilename.empty()) { + if (!BinaryFilename.empty() && (DebugInfod || !DebugFileDirectory.empty())) + exitWithError("Expected only one of -binary-file, -debuginfod or " + "-debug-file-directory"); + } else if (!BinaryFilename.empty() || DebugInfod || + !DebugFileDirectory.empty()) { + exitWithError("Expected only one of -debug-info, -binary-file, -debuginfod " + "or -debug-file-directory"); + } std::string CorrelateFilename; ProfCorrelatorKind CorrelateKind = ProfCorrelatorKind::NONE; if (!DebugInfoFilename.empty()) { @@ -936,6 +967,25 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs, exitWithError(std::move(Err), CorrelateFilename); } + ProfCorrelatorKind BIDFetcherCorrelateKind = ProfCorrelatorKind::NONE; + std::unique_ptr BIDFetcher; + if (DebugInfod) { + llvm::HTTPClient::initialize(); + BIDFetcher = std::make_unique(DebugFileDirectory); + if (!BIDFetcherProfileCorrelate) + exitWithError("Expected --correlate when --debuginfod is provided"); + BIDFetcherCorrelateKind = BIDFetcherProfileCorrelate; + } else if (!DebugFileDirectory.empty()) { + BIDFetcher = std::make_unique(DebugFileDirectory); + if (!BIDFetcherProfileCorrelate) + exitWithError("Expected --correlate when --debug-file-directory " + "is provided"); + BIDFetcherCorrelateKind = BIDFetcherProfileCorrelate; + } else if (BIDFetcherProfileCorrelate) { + exitWithError("Expected --debuginfod or --debug-file-directory when " + "--correlate is provided"); + } + std::mutex ErrorLock; SmallSet WriterErrorCodes; @@ -954,7 +1004,7 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs, if (NumThreads == 1) { for (const auto &Input : Inputs) loadInput(Input, Remapper, Correlator.get(), ProfiledBinary, - Contexts[0].get()); + Contexts[0].get(), BIDFetcher.get(), &BIDFetcherCorrelateKind); } else { DefaultThreadPool Pool(hardware_concurrency(NumThreads)); @@ -962,7 +1012,8 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs, unsigned Ctx = 0; for (const auto &Input : Inputs) { Pool.async(loadInput, Input, Remapper, Correlator.get(), ProfiledBinary, - Contexts[Ctx].get()); + Contexts[Ctx].get(), BIDFetcher.get(), + &BIDFetcherCorrelateKind); Ctx = (Ctx + 1) % NumThreads; } Pool.wait();