[llvm] 932d7b9 - [memprof] Print out profile build ids in the error message.

Snehasish Kumar via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 17 10:54:02 PDT 2023


Author: Snehasish Kumar
Date: 2023-04-17T17:53:57Z
New Revision: 932d7b9ddd23bfbe9ac1e8a2dabab8e457993ed4

URL: https://github.com/llvm/llvm-project/commit/932d7b9ddd23bfbe9ac1e8a2dabab8e457993ed4
DIFF: https://github.com/llvm/llvm-project/commit/932d7b9ddd23bfbe9ac1e8a2dabab8e457993ed4.diff

LOG: [memprof] Print out profile build ids in the error message.

When no --profiled-binary flag is provided we can print out the build
ids of the modules in the profile. This can help the user fetch the
correct binary from e.g. remote object store.

Reviewed By: tejohnson

Differential Revision: https://reviews.llvm.org/D148301

Added: 
    

Modified: 
    llvm/include/llvm/ProfileData/RawMemProfReader.h
    llvm/lib/ProfileData/RawMemProfReader.cpp
    llvm/test/tools/llvm-profdata/memprof-buildid.test

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ProfileData/RawMemProfReader.h b/llvm/include/llvm/ProfileData/RawMemProfReader.h
index 52d5f12fc7972..63bf819225dc7 100644
--- a/llvm/include/llvm/ProfileData/RawMemProfReader.h
+++ b/llvm/include/llvm/ProfileData/RawMemProfReader.h
@@ -57,6 +57,9 @@ class RawMemProfReader {
   create(const Twine &Path, const StringRef ProfiledBinary,
          bool KeepName = false);
 
+  // Returns a list of build ids recorded in the segment information.
+  static std::vector<std::string> peekBuildIds(MemoryBuffer *DataBuffer);
+
   using GuidMemProfRecordPair = std::pair<GlobalValue::GUID, MemProfRecord>;
   using Iterator = InstrProfIterator<GuidMemProfRecordPair, RawMemProfReader>;
   Iterator end() { return Iterator(); }

diff  --git a/llvm/lib/ProfileData/RawMemProfReader.cpp b/llvm/lib/ProfileData/RawMemProfReader.cpp
index 1c7323ea37630..7c519ed492e45 100644
--- a/llvm/lib/ProfileData/RawMemProfReader.cpp
+++ b/llvm/lib/ProfileData/RawMemProfReader.cpp
@@ -17,9 +17,12 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Twine.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
 #include "llvm/DebugInfo/Symbolize/SymbolizableObjectFile.h"
@@ -34,6 +37,7 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
 
 #define DEBUG_TYPE "memprof"
@@ -185,10 +189,20 @@ RawMemProfReader::create(const Twine &Path, const StringRef ProfiledBinary,
   if (Error E = checkBuffer(*Buffer))
     return report(std::move(E), Path.getSingleStringRef());
 
-  if (ProfiledBinary.empty())
+  if (ProfiledBinary.empty()) {
+    // Peek the build ids to print a helpful error message.
+    const std::vector<std::string> BuildIds = peekBuildIds(Buffer.get());
+    std::string ErrorMessage(
+        R"(Path to profiled binary is empty, expected binary with one of the following build ids:
+)");
+    for (const auto &Id : BuildIds) {
+      ErrorMessage += "\n BuildId: ";
+      ErrorMessage += Id;
+    }
     return report(
-        errorCodeToError(make_error_code(std::errc::invalid_argument)),
-        "Path to profiled binary is empty!");
+        make_error<StringError>(ErrorMessage, inconvertibleErrorCode()),
+        /*Context=*/"");
+  }
 
   auto BinaryOr = llvm::object::createBinary(ProfiledBinary);
   if (!BinaryOr) {
@@ -522,6 +536,36 @@ Error RawMemProfReader::symbolizeAndFilterStackFrames() {
   return Error::success();
 }
 
+std::vector<std::string>
+RawMemProfReader::peekBuildIds(MemoryBuffer *DataBuffer) {
+  const char *Next = DataBuffer->getBufferStart();
+  // Use a set + vector since a profile file may contain multiple raw profile
+  // dumps, each with segment information. We want them unique and in order they
+  // were stored in the profile; the profiled binary should be the first entry.
+  // The runtime uses dl_iterate_phdr and the "... first object visited by
+  // callback is the main program."
+  // https://man7.org/linux/man-pages/man3/dl_iterate_phdr.3.html
+  std::vector<std::string> BuildIds;
+  llvm::SmallSet<StringRef, 4> BuildIdsSet;
+  while (Next < DataBuffer->getBufferEnd()) {
+    auto *Header = reinterpret_cast<const memprof::Header *>(Next);
+
+    const llvm::SmallVector<SegmentEntry> Entries =
+        readSegmentEntries(Next + Header->SegmentOffset);
+
+    for (const auto &Entry : Entries) {
+      const std::string Id = getBuildIdString(Entry);
+      if (BuildIdsSet.contains(Id))
+        continue;
+      BuildIds.push_back(Id);
+      BuildIdsSet.insert(BuildIds.back());
+    }
+
+    Next += Header->TotalSize;
+  }
+  return BuildIds;
+}
+
 Error RawMemProfReader::readRawProfile(
     std::unique_ptr<MemoryBuffer> DataBuffer) {
   const char *Next = DataBuffer->getBufferStart();

diff  --git a/llvm/test/tools/llvm-profdata/memprof-buildid.test b/llvm/test/tools/llvm-profdata/memprof-buildid.test
index 9b055d3a70bbe..a5abe6ea7dcb6 100644
--- a/llvm/test/tools/llvm-profdata/memprof-buildid.test
+++ b/llvm/test/tools/llvm-profdata/memprof-buildid.test
@@ -5,8 +5,12 @@ RUN: llvm-readelf --notes %p/Inputs/buildid.memprofexe > %t1.txt
 RUN: llvm-profdata show --memory %p/Inputs/buildid.memprofraw --profiled-binary %p/Inputs/buildid.memprofexe -o -  > %t2.txt
 RUN: cat %t1.txt %t2.txt | FileCheck %s
 
+Test that we print out the profile build ids when --profiled-binary is empty. 
+RUN: not llvm-profdata show --memory %p/Inputs/buildid.memprofraw -o - 2> %t3.txt
+RUN: cat %t1.txt %t3.txt | FileCheck %s
+
 COM: First extract the id from the llvm-readelf output.
 CHECK: Build ID: [[ID:[[:xdigit:]]+]]
 
 COM: Then match it with the profdata output.
-CHECK: BuildId: {{.*}}[[ID]]
+CHECK-COUNT-1: BuildId: {{.*}}[[ID]]


        


More information about the llvm-commits mailing list