[memprof] Record BuildIDs in the raw profile.
authorSnehasish Kumar <snehasishk@google.com>
Mon, 13 Mar 2023 20:11:58 +0000 (20:11 +0000)
committerSnehasish Kumar <snehasishk@google.com>
Tue, 14 Mar 2023 18:16:38 +0000 (18:16 +0000)
This patch adds support for recording BuildIds usng the sanitizer
ListOfModules API. We add another entry to the SegmentEntry struct and
change the memprof raw version.

Reviewed By: tejohnson

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

27 files changed:
clang/test/CodeGen/Inputs/memprof.exe
clang/test/CodeGen/Inputs/memprof.memprofraw
compiler-rt/include/profile/MemProfData.inc
compiler-rt/lib/memprof/memprof_allocator.cpp
compiler-rt/lib/memprof/memprof_rawprofile.cpp
compiler-rt/lib/memprof/memprof_rawprofile.h
compiler-rt/lib/memprof/tests/rawprofile.cpp
llvm/include/llvm/ProfileData/MemProfData.inc
llvm/lib/ProfileData/RawMemProfReader.cpp
llvm/test/Transforms/PGOProfile/Inputs/memprof.exe
llvm/test/Transforms/PGOProfile/Inputs/memprof.memprofraw
llvm/test/Transforms/PGOProfile/Inputs/memprof_pgo.profraw
llvm/test/tools/llvm-profdata/Inputs/basic.memprofexe
llvm/test/tools/llvm-profdata/Inputs/basic.memprofraw
llvm/test/tools/llvm-profdata/Inputs/buildid.memprofexe [new file with mode: 0755]
llvm/test/tools/llvm-profdata/Inputs/buildid.memprofraw [new file with mode: 0644]
llvm/test/tools/llvm-profdata/Inputs/inline.memprofexe
llvm/test/tools/llvm-profdata/Inputs/inline.memprofraw
llvm/test/tools/llvm-profdata/Inputs/multi.memprofexe
llvm/test/tools/llvm-profdata/Inputs/multi.memprofraw
llvm/test/tools/llvm-profdata/Inputs/pic.memprofexe
llvm/test/tools/llvm-profdata/Inputs/pic.memprofraw
llvm/test/tools/llvm-profdata/Inputs/update_memprof_inputs.sh
llvm/test/tools/llvm-profdata/memprof-basic.test
llvm/test/tools/llvm-profdata/memprof-buildid.test [new file with mode: 0644]
llvm/test/tools/llvm-profdata/memprof-inline.test
llvm/test/tools/llvm-profdata/memprof-multi.test

index ad7a0414e899ef721069d2b754aa0fce5b51f979..bde5f3e29a3c2fecaff900fa230802c8ff171825 100755 (executable)
Binary files a/clang/test/CodeGen/Inputs/memprof.exe and b/clang/test/CodeGen/Inputs/memprof.exe differ
index e64214a51b0865be99b4d9c7577b83eeda5f664d..a7aa405a9c3a875954cf4b23bec21489f889ff0f 100644 (file)
Binary files a/clang/test/CodeGen/Inputs/memprof.memprofraw and b/clang/test/CodeGen/Inputs/memprof.memprofraw differ
index c533073da751f29ac03b2c027ca4a31da423db3b..b82a4baf6dd74e65d4b14ce330575df6a5d9f4db 100644 (file)
@@ -19,6 +19,7 @@
  * synced up.
  *
 \*===----------------------------------------------------------------------===*/
+#include <string.h>
 
 #ifdef _MSC_VER
 #define PACKED(...) __pragma(pack(push,1)) __VA_ARGS__ __pragma(pack(pop))
@@ -32,7 +33,9 @@
    (uint64_t)'o' << 24 | (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129)
 
 // The version number of the raw binary format.
-#define MEMPROF_RAW_VERSION 2ULL
+#define MEMPROF_RAW_VERSION 3ULL
+
+#define MEMPROF_BUILDID_MAX_SIZE 32ULL
 
 namespace llvm {
 namespace memprof {
@@ -46,37 +49,40 @@ PACKED(struct Header {
   uint64_t StackOffset;
 });
 
-
 // A struct describing the information necessary to describe a /proc/maps
 // segment entry for a particular binary/library identified by its build id.
 PACKED(struct SegmentEntry {
   uint64_t Start;
   uint64_t End;
   uint64_t Offset;
-  // This field is unused until sanitizer procmaps support for build ids for
-  // Linux-Elf is implemented.
-  uint8_t BuildId[32] = {0};
+  uint64_t BuildIdSize;
+  uint8_t BuildId[MEMPROF_BUILDID_MAX_SIZE] = {0};
 
-  SegmentEntry(uint64_t S, uint64_t E, uint64_t O) :
-    Start(S), End(E), Offset(O) {}
+  // This constructor is only used in tests so don't set the BuildId.
+  SegmentEntry(uint64_t S, uint64_t E, uint64_t O)
+      : Start(S), End(E), Offset(O), BuildIdSize(0) {}
 
   SegmentEntry(const SegmentEntry& S) {
     Start = S.Start;
     End = S.End;
     Offset = S.Offset;
+    BuildIdSize = S.BuildIdSize;
+    memcpy(BuildId, S.BuildId, S.BuildIdSize);
   }
 
   SegmentEntry& operator=(const SegmentEntry& S) {
     Start = S.Start;
     End = S.End;
     Offset = S.Offset;
+    BuildIdSize = S.BuildIdSize;
+    memcpy(BuildId, S.BuildId, S.BuildIdSize);
     return *this;
   }
 
   bool operator==(const SegmentEntry& S) const {
-    return Start == S.Start &&
-           End == S.End &&
-           Offset == S.Offset;
+    return Start == S.Start && End == S.End && Offset == S.Offset &&
+           BuildIdSize == S.BuildIdSize &&
+           memcmp(BuildId, S.BuildId, S.BuildIdSize) == 0;
   }
 });
 
index 6e3fa7f2dc7b1a5dfe18cf3f2651e51afc95df75..51c3a66ebd68071c803ebf60eca656383ca07c98 100644 (file)
 #include "sanitizer_common/sanitizer_allocator_checks.h"
 #include "sanitizer_common/sanitizer_allocator_interface.h"
 #include "sanitizer_common/sanitizer_allocator_report.h"
+#include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_errno.h"
 #include "sanitizer_common/sanitizer_file.h"
 #include "sanitizer_common/sanitizer_flags.h"
 #include "sanitizer_common/sanitizer_internal_defs.h"
-#include "sanitizer_common/sanitizer_procmaps.h"
 #include "sanitizer_common/sanitizer_stackdepot.h"
 
 #include <sched.h>
@@ -295,8 +295,10 @@ struct Allocator {
       // memprof_rawprofile.h.
       char *Buffer = nullptr;
 
-      MemoryMappingLayout Layout(/*cache_enabled=*/true);
-      u64 BytesSerialized = SerializeToRawProfile(MIBMap, Layout, Buffer);
+      __sanitizer::ListOfModules List;
+      List.init();
+      ArrayRef<LoadedModule> Modules(List.begin(), List.end());
+      u64 BytesSerialized = SerializeToRawProfile(MIBMap, Modules, Buffer);
       CHECK(Buffer && BytesSerialized && "could not serialize to buffer");
       report_file.Write(Buffer, BytesSerialized);
     }
index 88f3c34f85549c810b7fa9a93d2e09f83befaa36..1a65fbbf6b1e207ac80e3edbd510c4f8032c22a1 100644 (file)
@@ -33,12 +33,14 @@ void RecordStackId(const uptr Key, UNUSED LockedMemInfoBlock *const &MIB,
 }
 } // namespace
 
-u64 SegmentSizeBytes(MemoryMappingLayoutBase &Layout) {
+u64 SegmentSizeBytes(ArrayRef<LoadedModule> Modules) {
   u64 NumSegmentsToRecord = 0;
-  MemoryMappedSegment segment;
-  for (Layout.Reset(); Layout.Next(&segment);)
-    if (segment.IsReadable() && segment.IsExecutable())
-      NumSegmentsToRecord++;
+  for (const auto &Module : Modules) {
+    for (const auto &Segment : Module.ranges()) {
+      if (Segment.executable)
+        NumSegmentsToRecord++;
+    }
+  }
 
   return sizeof(u64) // A header which stores the number of records.
          + sizeof(SegmentEntry) * NumSegmentsToRecord;
@@ -51,28 +53,31 @@ u64 SegmentSizeBytes(MemoryMappingLayoutBase &Layout) {
 // Start
 // End
 // Offset
-// BuildID 32B
+// UuidSize
+// Uuid 32B
 // ----------
 // ...
-void SerializeSegmentsToBuffer(MemoryMappingLayoutBase &Layout,
+void SerializeSegmentsToBuffer(ArrayRef<LoadedModule> Modules,
                                const u64 ExpectedNumBytes, char *&Buffer) {
   char *Ptr = Buffer;
   // Reserve space for the final count.
   Ptr += sizeof(u64);
 
   u64 NumSegmentsRecorded = 0;
-  MemoryMappedSegment segment;
-
-  for (Layout.Reset(); Layout.Next(&segment);) {
-    if (segment.IsReadable() && segment.IsExecutable()) {
-      // TODO: Record segment.uuid when it is implemented for Linux-Elf.
-      SegmentEntry Entry(segment.start, segment.end, segment.offset);
-      memcpy(Ptr, &Entry, sizeof(SegmentEntry));
-      Ptr += sizeof(SegmentEntry);
-      NumSegmentsRecorded++;
+
+  for (const auto &Module : Modules) {
+    for (const auto &Segment : Module.ranges()) {
+      if (Segment.executable) {
+        SegmentEntry Entry(Segment.beg, Segment.end, Module.base_address());
+        CHECK(Module.uuid_size() <= MEMPROF_BUILDID_MAX_SIZE);
+        Entry.BuildIdSize = Module.uuid_size();
+        memcpy(Entry.BuildId, Module.uuid(), Module.uuid_size());
+        memcpy(Ptr, &Entry, sizeof(SegmentEntry));
+        Ptr += sizeof(SegmentEntry);
+        NumSegmentsRecorded++;
+      }
     }
   }
-
   // Store the number of segments we recorded in the space we reserved.
   *((u64 *)Buffer) = NumSegmentsRecorded;
   CHECK(ExpectedNumBytes >= static_cast<u64>(Ptr - Buffer) &&
@@ -198,11 +203,11 @@ void SerializeMIBInfoToBuffer(MIBMapTy &MIBMap, const Vector<u64> &StackIds,
 // ----------
 // Optional Padding Bytes
 // ...
-u64 SerializeToRawProfile(MIBMapTy &MIBMap, MemoryMappingLayoutBase &Layout,
+u64 SerializeToRawProfile(MIBMapTy &MIBMap, ArrayRef<LoadedModule> Modules,
                           char *&Buffer) {
   // Each section size is rounded up to 8b since the first entry in each section
   // is a u64 which holds the number of entries in the section by convention.
-  const u64 NumSegmentBytes = RoundUpTo(SegmentSizeBytes(Layout), 8);
+  const u64 NumSegmentBytes = RoundUpTo(SegmentSizeBytes(Modules), 8);
 
   Vector<u64> StackIds;
   MIBMap.ForEach(RecordStackId, reinterpret_cast<void *>(&StackIds));
@@ -232,7 +237,7 @@ u64 SerializeToRawProfile(MIBMapTy &MIBMap, MemoryMappingLayoutBase &Layout,
                 sizeof(Header) + NumSegmentBytes + NumMIBInfoBytes};
   Ptr = WriteBytes(header, Ptr);
 
-  SerializeSegmentsToBuffer(Layout, NumSegmentBytes, Ptr);
+  SerializeSegmentsToBuffer(Modules, NumSegmentBytes, Ptr);
   Ptr += NumSegmentBytes;
 
   SerializeMIBInfoToBuffer(MIBMap, StackIds, NumMIBInfoBytes, Ptr);
index 575104e7e34ebe0ca41a3ac634f613178ba25609..a4e9fd4232b5d358f5e33bd8ae6a7b2db07c348b 100644 (file)
@@ -2,12 +2,12 @@
 #define MEMPROF_RAWPROFILE_H_
 
 #include "memprof_mibmap.h"
-#include "sanitizer_common/sanitizer_procmaps.h"
+#include "sanitizer_common/sanitizer_common.h"
 
 namespace __memprof {
 // Serialize the in-memory representation of the memprof profile to the raw
 // binary format. The format itself is documented memprof_rawprofile.cpp.
-u64 SerializeToRawProfile(MIBMapTy &BlockCache, MemoryMappingLayoutBase &Layout,
+u64 SerializeToRawProfile(MIBMapTy &BlockCache, ArrayRef<LoadedModule> Modules,
                           char *&Buffer);
 } // namespace __memprof
 
index 7f6398d1cf86e07f5b79c149967d41f77c5ae317..3c7372afaedaa5bc5068aedd0a84a42f934d23f3 100644 (file)
@@ -15,22 +15,9 @@ namespace {
 
 using ::__memprof::MIBMapTy;
 using ::__memprof::SerializeToRawProfile;
-using ::__sanitizer::MemoryMappedSegment;
-using ::__sanitizer::MemoryMappingLayoutBase;
 using ::__sanitizer::StackDepotPut;
 using ::__sanitizer::StackTrace;
 using ::llvm::memprof::MemInfoBlock;
-using ::testing::_;
-using ::testing::Action;
-using ::testing::DoAll;
-using ::testing::Return;
-using ::testing::SetArgPointee;
-
-class MockMemoryMappingLayout final : public MemoryMappingLayoutBase {
-public:
-  MOCK_METHOD(bool, Next, (MemoryMappedSegment *), (override));
-  MOCK_METHOD(void, Reset, (), (override));
-};
 
 uint64_t PopulateFakeMap(const MemInfoBlock &FakeMIB, uint64_t StackPCBegin,
                          MIBMapTy &FakeMap) {
@@ -56,26 +43,13 @@ template <class T = uint64_t> T Read(char *&Buffer) {
 }
 
 TEST(MemProf, Basic) {
-  MockMemoryMappingLayout Layout;
-  MemoryMappedSegment FakeSegment;
-  memset(&FakeSegment, 0, sizeof(FakeSegment));
-  FakeSegment.start = 0x10;
-  FakeSegment.end = 0x20;
-  FakeSegment.offset = 0x10;
-  uint8_t uuid[__sanitizer::kModuleUUIDSize] = {0xC, 0x0, 0xF, 0xF, 0xE, 0xE};
-  memcpy(FakeSegment.uuid, uuid, __sanitizer::kModuleUUIDSize);
-  FakeSegment.protection =
-      __sanitizer::kProtectionExecute | __sanitizer::kProtectionRead;
-
-  const Action<bool(MemoryMappedSegment *)> SetSegment =
-      DoAll(SetArgPointee<0>(FakeSegment), Return(true));
-  EXPECT_CALL(Layout, Next(_))
-      .WillOnce(SetSegment)
-      .WillOnce(Return(false))
-      .WillOnce(SetSegment)
-      .WillRepeatedly(Return(false));
-
-  EXPECT_CALL(Layout, Reset).Times(2);
+  __sanitizer::LoadedModule FakeModule;
+  FakeModule.addAddressRange(/*begin=*/0x10, /*end=*/0x20, /*executable=*/true,
+                             /*writable=*/false, /*name=*/"");
+  const char uuid[MEMPROF_BUILDID_MAX_SIZE] = {0xC, 0x0, 0xF, 0xF, 0xE, 0xE};
+  FakeModule.setUuid(uuid, MEMPROF_BUILDID_MAX_SIZE);
+  __sanitizer::ArrayRef<__sanitizer::LoadedModule> Modules(&FakeModule,
+                                                           (&FakeModule) + 1);
 
   MIBMapTy FakeMap;
   MemInfoBlock FakeMIB;
@@ -90,7 +64,7 @@ TEST(MemProf, Basic) {
   FakeIds[1] = PopulateFakeMap(FakeMIB, /*StackPCBegin=*/3, FakeMap);
 
   char *Ptr = nullptr;
-  uint64_t NumBytes = SerializeToRawProfile(FakeMap, Layout, Ptr);
+  uint64_t NumBytes = SerializeToRawProfile(FakeMap, Modules, Ptr);
   const char *Buffer = Ptr;
 
   ASSERT_GT(NumBytes, 0ULL);
@@ -111,16 +85,16 @@ TEST(MemProf, Basic) {
   // Should be equal to the size of the raw profile header.
   EXPECT_EQ(SegmentOffset, 48ULL);
 
-  // We expect only 1 segment entry, 8b for the count and 56b for SegmentEntry
+  // We expect only 1 segment entry, 8b for the count and 64b for SegmentEntry
   // in memprof_rawprofile.cpp.
-  EXPECT_EQ(MIBOffset - SegmentOffset, 64ULL);
+  EXPECT_EQ(MIBOffset - SegmentOffset, 72ULL);
 
-  EXPECT_EQ(MIBOffset, 112ULL);
+  EXPECT_EQ(MIBOffset, 120ULL);
   // We expect 2 mib entry, 8b for the count and sizeof(uint64_t) +
   // sizeof(MemInfoBlock) contains stack id + MeminfoBlock.
   EXPECT_EQ(StackOffset - MIBOffset, 8 + 2 * (8 + sizeof(MemInfoBlock)));
 
-  EXPECT_EQ(StackOffset, 336ULL);
+  EXPECT_EQ(StackOffset, 408ULL);
   // We expect 2 stack entries, with 5 frames - 8b for total count,
   // 2 * (8b for id, 8b for frame count and 5*8b for fake frames).
   // Since this is the last section, there may be additional padding at the end
@@ -128,16 +102,15 @@ TEST(MemProf, Basic) {
   EXPECT_GE(TotalSize - StackOffset, 8ULL + 2 * (8 + 8 + 5 * 8));
 
   // ============= Check contents.
-  // The Uuid field is not yet populated on Linux-Elf by the sanitizer procmaps
-  // library, so we expect it to be filled with 0 for now.
-  unsigned char ExpectedSegmentBytes[64] = {
-      0x01, 0, 0, 0, 0, 0, 0, 0, // Number of entries
-      0x10, 0, 0, 0, 0, 0, 0, 0, // Start
-      0x20, 0, 0, 0, 0, 0, 0, 0, // End
-      0x10, 0, 0, 0, 0, 0, 0, 0, // Offset
-      0x0,                       // Uuid
+  unsigned char ExpectedSegmentBytes[72] = {
+      0x01, 0,   0,   0,   0,   0,  0, 0, // Number of entries
+      0x10, 0,   0,   0,   0,   0,  0, 0, // Start
+      0x20, 0,   0,   0,   0,   0,  0, 0, // End
+      0x0,  0,   0,   0,   0,   0,  0, 0, // Offset
+      0x20, 0,   0,   0,   0,   0,  0, 0, // UuidSize
+      0xC,  0x0, 0xF, 0xF, 0xE, 0xE       // Uuid
   };
-  EXPECT_EQ(memcmp(Buffer + SegmentOffset, ExpectedSegmentBytes, 64), 0);
+  EXPECT_EQ(memcmp(Buffer + SegmentOffset, ExpectedSegmentBytes, 72), 0);
 
   // Check that the number of entries is 2.
   EXPECT_EQ(*reinterpret_cast<const uint64_t *>(Buffer + MIBOffset), 2ULL);
@@ -193,5 +166,4 @@ TEST(MemProf, Basic) {
                    sizeof(ExpectedStackBytes[1])),
             0);
 }
-
 } // namespace
index c533073da751f29ac03b2c027ca4a31da423db3b..b82a4baf6dd74e65d4b14ce330575df6a5d9f4db 100644 (file)
@@ -19,6 +19,7 @@
  * synced up.
  *
 \*===----------------------------------------------------------------------===*/
+#include <string.h>
 
 #ifdef _MSC_VER
 #define PACKED(...) __pragma(pack(push,1)) __VA_ARGS__ __pragma(pack(pop))
@@ -32,7 +33,9 @@
    (uint64_t)'o' << 24 | (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129)
 
 // The version number of the raw binary format.
-#define MEMPROF_RAW_VERSION 2ULL
+#define MEMPROF_RAW_VERSION 3ULL
+
+#define MEMPROF_BUILDID_MAX_SIZE 32ULL
 
 namespace llvm {
 namespace memprof {
@@ -46,37 +49,40 @@ PACKED(struct Header {
   uint64_t StackOffset;
 });
 
-
 // A struct describing the information necessary to describe a /proc/maps
 // segment entry for a particular binary/library identified by its build id.
 PACKED(struct SegmentEntry {
   uint64_t Start;
   uint64_t End;
   uint64_t Offset;
-  // This field is unused until sanitizer procmaps support for build ids for
-  // Linux-Elf is implemented.
-  uint8_t BuildId[32] = {0};
+  uint64_t BuildIdSize;
+  uint8_t BuildId[MEMPROF_BUILDID_MAX_SIZE] = {0};
 
-  SegmentEntry(uint64_t S, uint64_t E, uint64_t O) :
-    Start(S), End(E), Offset(O) {}
+  // This constructor is only used in tests so don't set the BuildId.
+  SegmentEntry(uint64_t S, uint64_t E, uint64_t O)
+      : Start(S), End(E), Offset(O), BuildIdSize(0) {}
 
   SegmentEntry(const SegmentEntry& S) {
     Start = S.Start;
     End = S.End;
     Offset = S.Offset;
+    BuildIdSize = S.BuildIdSize;
+    memcpy(BuildId, S.BuildId, S.BuildIdSize);
   }
 
   SegmentEntry& operator=(const SegmentEntry& S) {
     Start = S.Start;
     End = S.End;
     Offset = S.Offset;
+    BuildIdSize = S.BuildIdSize;
+    memcpy(BuildId, S.BuildId, S.BuildIdSize);
     return *this;
   }
 
   bool operator==(const SegmentEntry& S) const {
-    return Start == S.Start &&
-           End == S.End &&
-           Offset == S.Offset;
+    return Start == S.Start && End == S.End && Offset == S.Offset &&
+           BuildIdSize == S.BuildIdSize &&
+           memcmp(BuildId, S.BuildId, S.BuildIdSize) == 0;
   }
 });
 
index 958bbc551f28113783e958907c000b7a9edb38bc..dd62a2f8a0f6c649af84336c72c3d9cea9ab3a22 100644 (file)
@@ -158,15 +158,13 @@ bool isRuntimePath(const StringRef Path) {
 }
 
 std::string getBuildIdString(const SegmentEntry &Entry) {
-  constexpr size_t Size = sizeof(Entry.BuildId) / sizeof(uint8_t);
-  constexpr uint8_t Zeros[Size] = {0};
   // If the build id is unset print a helpful string instead of all zeros.
-  if (memcmp(Entry.BuildId, Zeros, Size) == 0)
+  if (Entry.BuildIdSize == 0)
     return "<None>";
 
   std::string Str;
   raw_string_ostream OS(Str);
-  for (size_t I = 0; I < Size; I++) {
+  for (size_t I = 0; I < Entry.BuildIdSize; I++) {
     OS << format_hex_no_prefix(Entry.BuildId[I], 2);
   }
   return OS.str();
index 0ed40163919ccba7e22b2b90abe69f0cf71c28a9..b10c2f9c72147e901d794216d274a349552996d0 100755 (executable)
Binary files a/llvm/test/Transforms/PGOProfile/Inputs/memprof.exe and b/llvm/test/Transforms/PGOProfile/Inputs/memprof.exe differ
index 7511ca78474f508e58f27357ef5e2b587a31bb2d..790249a44b0d136bc195221d670b37ea4de9bf55 100644 (file)
Binary files a/llvm/test/Transforms/PGOProfile/Inputs/memprof.memprofraw and b/llvm/test/Transforms/PGOProfile/Inputs/memprof.memprofraw differ
index 04330fe95a0bbfb5a264192cc884555238bfcb32..d5160e75d5ec223b6a40919b2e4649700ce6efc7 100644 (file)
Binary files a/llvm/test/Transforms/PGOProfile/Inputs/memprof_pgo.profraw and b/llvm/test/Transforms/PGOProfile/Inputs/memprof_pgo.profraw differ
index d321a05e6d3e7dd165b3eb76ac33755295b43d1d..d03894b6d8e40c8ca8e1f94d5e328f936a052fde 100755 (executable)
Binary files a/llvm/test/tools/llvm-profdata/Inputs/basic.memprofexe and b/llvm/test/tools/llvm-profdata/Inputs/basic.memprofexe differ
index 612eaa0b54ca6fd39c0efbde64c3c1b5664e9f9f..62b7d299d3aa14bfac3ca2c8d9438ec976013052 100644 (file)
Binary files a/llvm/test/tools/llvm-profdata/Inputs/basic.memprofraw and b/llvm/test/tools/llvm-profdata/Inputs/basic.memprofraw differ
diff --git a/llvm/test/tools/llvm-profdata/Inputs/buildid.memprofexe b/llvm/test/tools/llvm-profdata/Inputs/buildid.memprofexe
new file mode 100755 (executable)
index 0000000..5687d06
Binary files /dev/null and b/llvm/test/tools/llvm-profdata/Inputs/buildid.memprofexe differ
diff --git a/llvm/test/tools/llvm-profdata/Inputs/buildid.memprofraw b/llvm/test/tools/llvm-profdata/Inputs/buildid.memprofraw
new file mode 100644 (file)
index 0000000..43f9ca9
Binary files /dev/null and b/llvm/test/tools/llvm-profdata/Inputs/buildid.memprofraw differ
index 6a5594eb7b207f85b1b646030e52d89d7335fc70..766d2c4713136b071e88012fb29e11a05a735704 100755 (executable)
Binary files a/llvm/test/tools/llvm-profdata/Inputs/inline.memprofexe and b/llvm/test/tools/llvm-profdata/Inputs/inline.memprofexe differ
index 8e0ad196057afebdca4cff52d81f9454e98934ab..26254ae67c7c2e3c528e997a07745c85dd87b9d3 100644 (file)
Binary files a/llvm/test/tools/llvm-profdata/Inputs/inline.memprofraw and b/llvm/test/tools/llvm-profdata/Inputs/inline.memprofraw differ
index 02100d049d61b697bfdfc41ac7f2154e999fba4e..d5c3ec65b3ac78a3a72b3b735d4e2135ff60078d 100755 (executable)
Binary files a/llvm/test/tools/llvm-profdata/Inputs/multi.memprofexe and b/llvm/test/tools/llvm-profdata/Inputs/multi.memprofexe differ
index 875669884afd50f3755f7d43ce9efb6edf9b7bcd..a1018aae2fba460ce492983e478799fc98efd235 100644 (file)
Binary files a/llvm/test/tools/llvm-profdata/Inputs/multi.memprofraw and b/llvm/test/tools/llvm-profdata/Inputs/multi.memprofraw differ
index 900a453bc14603c8dd14850b83186c1ae7811815..d854186380e7343cfeb1ab41260282189a63d886 100755 (executable)
Binary files a/llvm/test/tools/llvm-profdata/Inputs/pic.memprofexe and b/llvm/test/tools/llvm-profdata/Inputs/pic.memprofexe differ
index b56b9a98a7c8eff2302c1d64af345eafa507e31f..992022fa9129c997b0d0c6dffe189dbfbdfd9c4d 100644 (file)
Binary files a/llvm/test/tools/llvm-profdata/Inputs/pic.memprofraw and b/llvm/test/tools/llvm-profdata/Inputs/pic.memprofraw differ
index e709254d596293131a7dda4d66de82ff8292b811..5365a0bb6cc3a390f398ce3b9da00d519c755544 100755 (executable)
@@ -72,6 +72,7 @@ INPUTS["basic"]="BASIC"
 INPUTS["inline"]="INLINE"
 INPUTS["multi"]="MULTI"
 INPUTS["pic"]="BASIC;-pie"
+INPUTS["buildid"]="BASIC;-Wl,-build-id=sha1"
 
 for name in "${!INPUTS[@]}"; do
   IFS=";" read -r src flags <<< "${INPUTS[$name]}"
index 2d1725188cc19f741a9018410675d6991af66944..8eaa2fa1013f44ce0a58a628b2ecb71e3ae66d23 100644 (file)
@@ -8,17 +8,17 @@ additional allocations which do not originate from the main binary are pruned.
 
 CHECK:  MemprofProfile:
 CHECK-NEXT:   Summary:
-CHECK-NEXT:     Version: 2
+CHECK-NEXT:     Version: 3
 CHECK-NEXT:     NumSegments: {{[0-9]+}}
 CHECK-NEXT:     NumMibInfo: 2
 CHECK-NEXT:     NumAllocFunctions: 1
 CHECK-NEXT:     NumStackOffsets: 2
 CHECK-NEXT:   Segments:
 CHECK-NEXT:   -
-CHECK-NEXT:     BuildId: <None>
-CHECK-NEXT:     Start: 0x{{[0-9]+}}
-CHECK-NEXT:     End: 0x{{[0-9]+}}
-CHECK-NEXT:     Offset: 0x{{[0-9]+}}
+CHECK-NEXT:     BuildId: {{[[:xdigit:]]+}}
+CHECK-NEXT:     Start: 0x{{[[:xdigit:]]+}}
+CHECK-NEXT:     End: 0x{{[[:xdigit:]]+}}
+CHECK-NEXT:     Offset: 0x{{[[:xdigit:]]+}}
 CHECK-NEXT:   -
 
 CHECK:   Records:
diff --git a/llvm/test/tools/llvm-profdata/memprof-buildid.test b/llvm/test/tools/llvm-profdata/memprof-buildid.test
new file mode 100644 (file)
index 0000000..9b055d3
--- /dev/null
@@ -0,0 +1,12 @@
+REQUIRES: x86_64-linux
+
+To update the inputs used below run Inputs/update_memprof_inputs.sh /path/to/updated/clang
+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
+
+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]]
index 571beb921ea0cbf3a0f3e2a87f508a12fb5c0c92..dd842c054208311baabc8c22abb2d44c94634515 100644 (file)
@@ -5,17 +5,17 @@ RUN: llvm-profdata show --memory %p/Inputs/inline.memprofraw --profiled-binary %
 
 CHECK:  MemprofProfile:
 CHECK-NEXT:  Summary:
-CHECK-NEXT:    Version: 2
+CHECK-NEXT:    Version: 3
 CHECK-NEXT:    NumSegments: {{[0-9]+}}
 CHECK-NEXT:    NumMibInfo: 2
 CHECK-NEXT:    NumAllocFunctions: 2
 CHECK-NEXT:    NumStackOffsets: 1
 CHECK-NEXT:  Segments:
 CHECK-NEXT:  -
-CHECK-NEXT:    BuildId: <None>
-CHECK-NEXT:    Start: 0x{{[0-9]+}}
-CHECK-NEXT:    End: 0x{{[0-9]+}}
-CHECK-NEXT:    Offset: 0x{{[0-9]+}}
+CHECK-NEXT:    BuildId: {{[[:xdigit:]]+}}
+CHECK-NEXT:    Start: 0x{{[[:xdigit:]]+}}
+CHECK-NEXT:    End: 0x{{[[:xdigit:]]+}}
+CHECK-NEXT:    Offset: 0x{{[[:xdigit:]]+}}
 CHECK-NEXT:  -
 
 CHECK:  Records:
index 5918a957bd6f7d521c5fbb08b438c400e1fb506f..f3cdbd1f5266c18a69a47fc3337a71ec6cad429f 100644 (file)
@@ -7,7 +7,7 @@ We expect 2 MIB entries, 1 each for the malloc calls in the program.
 
 CHECK:  MemprofProfile:
 CHECK-NEXT:  Summary:
-CHECK-NEXT:    Version: 2
+CHECK-NEXT:    Version: 3
 CHECK-NEXT:    NumSegments: {{[0-9]+}}
 CHECK-NEXT:    NumMibInfo: 2
 CHECK-NEXT:    NumAllocFunctions: 1