[llvm] r363325 - [Coverage] Load code coverage data from archives

Vedant Kumar via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 13 13:48:57 PDT 2019


Author: vedantk
Date: Thu Jun 13 13:48:57 2019
New Revision: 363325

URL: http://llvm.org/viewvc/llvm-project?rev=363325&view=rev
Log:
[Coverage] Load code coverage data from archives

Support loading code coverage data from regular archives, thin archives,
and from MachO universal binaries which contain archives.

Testing: check-llvm, check-profile (with {A,UB}San enabled)

rdar://51538999

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

Added:
    llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/
    llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj1.c
    llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj1_32.o   (with props)
    llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj2.c
    llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj2_32.o   (with props)
    llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/universal_bin_wrapping_archives   (with props)
    llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/universal_bin_wrapping_archives.proftext
    llvm/trunk/test/tools/llvm-cov/universal_bin_wrapping_archives.test
Modified:
    llvm/trunk/docs/CommandGuide/llvm-cov.rst
    llvm/trunk/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
    llvm/trunk/lib/ProfileData/Coverage/CoverageMapping.cpp
    llvm/trunk/lib/ProfileData/Coverage/CoverageMappingReader.cpp

Modified: llvm/trunk/docs/CommandGuide/llvm-cov.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CommandGuide/llvm-cov.rst?rev=363325&r1=363324&r2=363325&view=diff
==============================================================================
--- llvm/trunk/docs/CommandGuide/llvm-cov.rst (original)
+++ llvm/trunk/docs/CommandGuide/llvm-cov.rst Thu Jun 13 13:48:57 2019
@@ -181,6 +181,9 @@ The :program:`llvm-cov show` command sho
 binaries *BIN*,...  using the profile data *PROFILE*. It can optionally be
 filtered to only show the coverage for the files listed in *SOURCES*.
 
+*BIN* may be an executable, object file, dynamic library, or archive (thin or
+otherwise).
+
 To use :program:`llvm-cov show`, you need a program that is compiled with
 instrumentation to emit profile and coverage data. To build such a program with
 ``clang`` use the ``-fprofile-instr-generate`` and ``-fcoverage-mapping``
@@ -331,6 +334,9 @@ The :program:`llvm-cov report` command d
 the binaries *BIN*,... using the profile data *PROFILE*. It can optionally be
 filtered to only show the coverage for the files listed in *SOURCES*.
 
+*BIN* may be an executable, object file, dynamic library, or archive (thin or
+otherwise).
+
 If no source files are provided, a summary line is printed for each file in the
 coverage data. If any files are provided, summaries can be shown for each
 function in the listed files if the ``-show-functions`` option is enabled.

Modified: llvm/trunk/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/Coverage/CoverageMappingReader.h?rev=363325&r1=363324&r2=363325&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ProfileData/Coverage/CoverageMappingReader.h (original)
+++ llvm/trunk/include/llvm/ProfileData/Coverage/CoverageMappingReader.h Thu Jun 13 13:48:57 2019
@@ -203,9 +203,15 @@ public:
   BinaryCoverageReader(const BinaryCoverageReader &) = delete;
   BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete;
 
+  static Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
+  create(MemoryBufferRef ObjectBuffer, StringRef Arch,
+         SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers);
+
   static Expected<std::unique_ptr<BinaryCoverageReader>>
-  create(std::unique_ptr<MemoryBuffer> &ObjectBuffer,
-         StringRef Arch);
+  createCoverageReaderFromBuffer(StringRef Coverage,
+                                 InstrProfSymtab &&ProfileNames,
+                                 uint8_t BytesInAddress,
+                                 support::endianness Endian);
 
   Error readNextRecord(CoverageMappingRecord &Record) override;
 };

Modified: llvm/trunk/lib/ProfileData/Coverage/CoverageMapping.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/Coverage/CoverageMapping.cpp?rev=363325&r1=363324&r2=363325&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/Coverage/CoverageMapping.cpp (original)
+++ llvm/trunk/lib/ProfileData/Coverage/CoverageMapping.cpp Thu Jun 13 13:48:57 2019
@@ -285,11 +285,14 @@ CoverageMapping::load(ArrayRef<StringRef
     if (std::error_code EC = CovMappingBufOrErr.getError())
       return errorCodeToError(EC);
     StringRef Arch = Arches.empty() ? StringRef() : Arches[File.index()];
-    auto CoverageReaderOrErr =
-        BinaryCoverageReader::create(CovMappingBufOrErr.get(), Arch);
-    if (Error E = CoverageReaderOrErr.takeError())
+    MemoryBufferRef CovMappingBufRef =
+        CovMappingBufOrErr.get()->getMemBufferRef();
+    auto CoverageReadersOrErr =
+        BinaryCoverageReader::create(CovMappingBufRef, Arch, Buffers);
+    if (Error E = CoverageReadersOrErr.takeError())
       return std::move(E);
-    Readers.push_back(std::move(CoverageReaderOrErr.get()));
+    for (auto &Reader : CoverageReadersOrErr.get())
+      Readers.push_back(std::move(Reader));
     Buffers.push_back(std::move(CovMappingBufOrErr.get()));
   }
   return load(Readers, *ProfileReader);

Modified: llvm/trunk/lib/ProfileData/Coverage/CoverageMappingReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/Coverage/CoverageMappingReader.cpp?rev=363325&r1=363324&r2=363325&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/Coverage/CoverageMappingReader.cpp (original)
+++ llvm/trunk/lib/ProfileData/Coverage/CoverageMappingReader.cpp Thu Jun 13 13:48:57 2019
@@ -586,12 +586,43 @@ static Error readCoverageMappingData(
 
 static const char *TestingFormatMagic = "llvmcovmtestdata";
 
-static Error loadTestingFormat(StringRef Data, InstrProfSymtab &ProfileNames,
-                               StringRef &CoverageMapping,
-                               uint8_t &BytesInAddress,
-                               support::endianness &Endian) {
-  BytesInAddress = 8;
-  Endian = support::endianness::little;
+Expected<std::unique_ptr<BinaryCoverageReader>>
+BinaryCoverageReader::createCoverageReaderFromBuffer(
+    StringRef Coverage, InstrProfSymtab &&ProfileNames, uint8_t BytesInAddress,
+    support::endianness Endian) {
+  std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader());
+  Reader->ProfileNames = std::move(ProfileNames);
+  if (BytesInAddress == 4 && Endian == support::endianness::little) {
+    if (Error E =
+            readCoverageMappingData<uint32_t, support::endianness::little>(
+                Reader->ProfileNames, Coverage, Reader->MappingRecords,
+                Reader->Filenames))
+      return std::move(E);
+  } else if (BytesInAddress == 4 && Endian == support::endianness::big) {
+    if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>(
+            Reader->ProfileNames, Coverage, Reader->MappingRecords,
+            Reader->Filenames))
+      return std::move(E);
+  } else if (BytesInAddress == 8 && Endian == support::endianness::little) {
+    if (Error E =
+            readCoverageMappingData<uint64_t, support::endianness::little>(
+                Reader->ProfileNames, Coverage, Reader->MappingRecords,
+                Reader->Filenames))
+      return std::move(E);
+  } else if (BytesInAddress == 8 && Endian == support::endianness::big) {
+    if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>(
+            Reader->ProfileNames, Coverage, Reader->MappingRecords,
+            Reader->Filenames))
+      return std::move(E);
+  } else
+    return make_error<CoverageMapError>(coveragemap_error::malformed);
+  return Reader;
+}
+
+static Expected<std::unique_ptr<BinaryCoverageReader>>
+loadTestingFormat(StringRef Data) {
+  uint8_t BytesInAddress = 8;
+  support::endianness Endian = support::endianness::little;
 
   Data = Data.substr(StringRef(TestingFormatMagic).size());
   if (Data.empty())
@@ -610,9 +641,10 @@ static Error loadTestingFormat(StringRef
   Data = Data.substr(N);
   if (Data.size() < ProfileNamesSize)
     return make_error<CoverageMapError>(coveragemap_error::malformed);
+  InstrProfSymtab ProfileNames;
   if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address))
-    return E;
-  CoverageMapping = Data.substr(ProfileNamesSize);
+    return std::move(E);
+  StringRef CoverageMapping = Data.substr(ProfileNamesSize);
   // Skip the padding bytes because coverage map data has an alignment of 8.
   if (CoverageMapping.empty())
     return make_error<CoverageMapError>(coveragemap_error::truncated);
@@ -620,7 +652,8 @@ static Error loadTestingFormat(StringRef
   if (CoverageMapping.size() < Pad)
     return make_error<CoverageMapError>(coveragemap_error::malformed);
   CoverageMapping = CoverageMapping.substr(Pad);
-  return Error::success();
+  return BinaryCoverageReader::createCoverageReaderFromBuffer(
+      CoverageMapping, std::move(ProfileNames), BytesInAddress, Endian);
 }
 
 static Expected<SectionRef> lookupSection(ObjectFile &OF, StringRef Name) {
@@ -643,15 +676,8 @@ static Expected<SectionRef> lookupSectio
   return make_error<CoverageMapError>(coveragemap_error::no_data_found);
 }
 
-static Error loadBinaryFormat(MemoryBufferRef ObjectBuffer,
-                              InstrProfSymtab &ProfileNames,
-                              StringRef &CoverageMapping,
-                              uint8_t &BytesInAddress,
-                              support::endianness &Endian, StringRef Arch) {
-  auto BinOrErr = createBinary(ObjectBuffer);
-  if (!BinOrErr)
-    return BinOrErr.takeError();
-  auto Bin = std::move(BinOrErr.get());
+static Expected<std::unique_ptr<BinaryCoverageReader>>
+loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch) {
   std::unique_ptr<ObjectFile> OF;
   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
     // If we have a universal binary, try to look up the object for the
@@ -671,9 +697,10 @@ static Error loadBinaryFormat(MemoryBuff
     return make_error<CoverageMapError>(coveragemap_error::malformed);
 
   // The coverage uses native pointer sizes for the object it's written in.
-  BytesInAddress = OF->getBytesInAddress();
-  Endian = OF->isLittleEndian() ? support::endianness::little
-                                : support::endianness::big;
+  uint8_t BytesInAddress = OF->getBytesInAddress();
+  support::endianness Endian = OF->isLittleEndian()
+                                   ? support::endianness::little
+                                   : support::endianness::big;
 
   // Look for the sections that we are interested in.
   auto ObjFormat = OF->getTripleObjectFormat();
@@ -681,66 +708,101 @@ static Error loadBinaryFormat(MemoryBuff
       lookupSection(*OF, getInstrProfSectionName(IPSK_name, ObjFormat,
                                                  /*AddSegmentInfo=*/false));
   if (auto E = NamesSection.takeError())
-    return E;
+    return std::move(E);
   auto CoverageSection =
       lookupSection(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat,
                                                  /*AddSegmentInfo=*/false));
   if (auto E = CoverageSection.takeError())
-    return E;
+    return std::move(E);
 
   // Get the contents of the given sections.
-  if (Expected<StringRef> E = CoverageSection->getContents())
-    CoverageMapping = *E;
-  else
-    return E.takeError();
+  auto CoverageMappingOrErr = CoverageSection->getContents();
+  if (!CoverageMappingOrErr)
+    return CoverageMappingOrErr.takeError();
 
+  InstrProfSymtab ProfileNames;
   if (Error E = ProfileNames.create(*NamesSection))
-    return E;
+    return std::move(E);
 
-  return Error::success();
+  return BinaryCoverageReader::createCoverageReaderFromBuffer(
+      CoverageMappingOrErr.get(), std::move(ProfileNames), BytesInAddress,
+      Endian);
 }
 
-Expected<std::unique_ptr<BinaryCoverageReader>>
-BinaryCoverageReader::create(std::unique_ptr<MemoryBuffer> &ObjectBuffer,
-                             StringRef Arch) {
-  std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader());
+Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
+BinaryCoverageReader::create(
+    MemoryBufferRef ObjectBuffer, StringRef Arch,
+    SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers) {
+  std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;
 
-  StringRef Coverage;
-  uint8_t BytesInAddress;
-  support::endianness Endian;
-  Error E = Error::success();
-  consumeError(std::move(E));
-  if (ObjectBuffer->getBuffer().startswith(TestingFormatMagic))
+  if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) {
     // This is a special format used for testing.
-    E = loadTestingFormat(ObjectBuffer->getBuffer(), Reader->ProfileNames,
-                          Coverage, BytesInAddress, Endian);
-  else
-    E = loadBinaryFormat(ObjectBuffer->getMemBufferRef(), Reader->ProfileNames,
-                         Coverage, BytesInAddress, Endian, Arch);
-  if (E)
-    return std::move(E);
+    auto ReaderOrErr = loadTestingFormat(ObjectBuffer.getBuffer());
+    if (!ReaderOrErr)
+      return ReaderOrErr.takeError();
+    Readers.push_back(std::move(ReaderOrErr.get()));
+    return Readers;
+  }
 
-  if (BytesInAddress == 4 && Endian == support::endianness::little)
-    E = readCoverageMappingData<uint32_t, support::endianness::little>(
-        Reader->ProfileNames, Coverage, Reader->MappingRecords,
-        Reader->Filenames);
-  else if (BytesInAddress == 4 && Endian == support::endianness::big)
-    E = readCoverageMappingData<uint32_t, support::endianness::big>(
-        Reader->ProfileNames, Coverage, Reader->MappingRecords,
-        Reader->Filenames);
-  else if (BytesInAddress == 8 && Endian == support::endianness::little)
-    E = readCoverageMappingData<uint64_t, support::endianness::little>(
-        Reader->ProfileNames, Coverage, Reader->MappingRecords,
-        Reader->Filenames);
-  else if (BytesInAddress == 8 && Endian == support::endianness::big)
-    E = readCoverageMappingData<uint64_t, support::endianness::big>(
-        Reader->ProfileNames, Coverage, Reader->MappingRecords,
-        Reader->Filenames);
-  else
-    return make_error<CoverageMapError>(coveragemap_error::malformed);
-  if (E)
-    return std::move(E);
-  return std::move(Reader);
+  auto BinOrErr = createBinary(ObjectBuffer);
+  if (!BinOrErr)
+    return BinOrErr.takeError();
+  std::unique_ptr<Binary> Bin = std::move(BinOrErr.get());
+
+  // MachO universal binaries which contain archives need to be treated as
+  // archives, not as regular binaries.
+  if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
+    for (auto &ObjForArch : Universal->objects()) {
+      // Skip slices within the universal binary which target the wrong arch.
+      std::string ObjArch = ObjForArch.getArchFlagName();
+      if (Arch != ObjArch)
+        continue;
+
+      auto ArchiveOrErr = ObjForArch.getAsArchive();
+      if (!ArchiveOrErr) {
+        // If this is not an archive, try treating it as a regular object.
+        consumeError(ArchiveOrErr.takeError());
+        break;
+      }
+
+      return BinaryCoverageReader::create(
+          ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers);
+    }
+  }
+
+  // Load coverage out of archive members.
+  if (auto *Ar = dyn_cast<Archive>(Bin.get())) {
+    Error Err = Error::success();
+    for (auto &Child : Ar->children(Err)) {
+      Expected<MemoryBufferRef> ChildBufOrErr = Child.getMemoryBufferRef();
+      if (!ChildBufOrErr)
+        return ChildBufOrErr.takeError();
+
+      auto ChildReadersOrErr = BinaryCoverageReader::create(
+          ChildBufOrErr.get(), Arch, ObjectFileBuffers);
+      if (!ChildReadersOrErr)
+        return ChildReadersOrErr.takeError();
+      for (auto &Reader : ChildReadersOrErr.get())
+        Readers.push_back(std::move(Reader));
+    }
+    if (Err)
+      return std::move(Err);
+
+    // Thin archives reference object files outside of the archive file, i.e.
+    // files which reside in memory not owned by the caller. Transfer ownership
+    // to the caller.
+    if (Ar->isThin())
+      for (auto &Buffer : Ar->takeThinBuffers())
+        ObjectFileBuffers.push_back(std::move(Buffer));
+
+    return Readers;
+  }
+
+  auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch);
+  if (!ReaderOrErr)
+    return ReaderOrErr.takeError();
+  Readers.push_back(std::move(ReaderOrErr.get()));
+  return Readers;
 }
 
 Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) {

Added: llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj1.c
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj1.c?rev=363325&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj1.c (added)
+++ llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj1.c Thu Jun 13 13:48:57 2019
@@ -0,0 +1 @@
+void f1() {}

Added: llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj1_32.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj1_32.o?rev=363325&view=auto
==============================================================================
Binary file - no diff available.

Propchange: llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj1_32.o
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj2.c
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj2.c?rev=363325&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj2.c (added)
+++ llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj2.c Thu Jun 13 13:48:57 2019
@@ -0,0 +1 @@
+void f2() {}

Added: llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj2_32.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj2_32.o?rev=363325&view=auto
==============================================================================
Binary file - no diff available.

Propchange: llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/obj2_32.o
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/universal_bin_wrapping_archives
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/universal_bin_wrapping_archives?rev=363325&view=auto
==============================================================================
Binary file - no diff available.

Propchange: llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/universal_bin_wrapping_archives
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/universal_bin_wrapping_archives.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/universal_bin_wrapping_archives.proftext?rev=363325&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/universal_bin_wrapping_archives.proftext (added)
+++ llvm/trunk/test/tools/llvm-cov/Inputs/universal_bin_wrapping_archives/universal_bin_wrapping_archives.proftext Thu Jun 13 13:48:57 2019
@@ -0,0 +1,8 @@
+f1
+0x0
+1
+100
+f2
+0x0
+1
+100

Added: llvm/trunk/test/tools/llvm-cov/universal_bin_wrapping_archives.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/universal_bin_wrapping_archives.test?rev=363325&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/universal_bin_wrapping_archives.test (added)
+++ llvm/trunk/test/tools/llvm-cov/universal_bin_wrapping_archives.test Thu Jun 13 13:48:57 2019
@@ -0,0 +1,44 @@
+The coverage reader should be able to handle archives, and archives embedded within
+MachO universal binaries.
+
+---
+Steps to re-generate these files on macOS:
+
+clang -fprofile-instr-generate -fcoverage-mapping -c obj1.c -o obj1_32.o -arch i386
+clang -fprofile-instr-generate -fcoverage-mapping -c obj2.c -o obj2_32.o -arch i386
+clang -fprofile-instr-generate -fcoverage-mapping -c obj1.c -o obj1_64.o -arch x86_64
+clang -fprofile-instr-generate -fcoverage-mapping -c obj2.c -o obj2_64.o -arch x86_64
+ar -q archive_32 obj1_32.o obj2_32.o
+ar -q archive_64 obj1_64.o obj2_64.o
+lipo -output universal_bin_wrapping_archives -create archive_32 archive_64
+---
+
+RUN: llvm-profdata merge %S/Inputs/universal_bin_wrapping_archives/universal_bin_wrapping_archives.proftext -o %t.profdata
+
+RUN: llvm-cov show %S/Inputs/universal_bin_wrapping_archives/universal_bin_wrapping_archives \
+RUN:   -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs/universal_bin_wrapping_archives %s -arch i386 \
+RUN:   | FileCheck %s --check-prefix=SHOW_ARCHIVE
+
+RUN: llvm-cov show %S/Inputs/universal_bin_wrapping_archives/universal_bin_wrapping_archives \
+RUN:   -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs/universal_bin_wrapping_archives %s -arch x86_64 \
+RUN:   | FileCheck %s --check-prefix=SHOW_ARCHIVE
+
+SHOW_ARCHIVE: {{.*}}obj1.c:
+SHOW_ARCHIVE-NEXT: 1|    100|void f1() {}
+SHOW_ARCHIVE: {{.*}}obj2.c:
+SHOW_ARCHIVE-NEXT: 1|    100|void f2() {}
+
+RUN: llvm-cov report %S/Inputs/universal_bin_wrapping_archives/universal_bin_wrapping_archives \
+RUN:   -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs/universal_bin_wrapping_archives %s -arch i386 \
+RUN:   | FileCheck %s --check-prefix=REPORT_ARCHIVE
+
+RUN: llvm-cov report %S/Inputs/universal_bin_wrapping_archives/universal_bin_wrapping_archives \
+RUN:   -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs/universal_bin_wrapping_archives %s -arch x86_64 \
+RUN:   | FileCheck %s --check-prefix=REPORT_ARCHIVE
+
+RUN: llvm-ar rcT %t.thin32.a %S/Inputs/universal_bin_wrapping_archives/obj1_32.o %S/Inputs/universal_bin_wrapping_archives/obj2_32.o
+RUN: llvm-cov report %t.thin32.a -instr-profile %t.profdata | FileCheck %s --check-prefix=REPORT_ARCHIVE
+
+REPORT_ARCHIVE: obj1.c 1 0 100.00% 1 0 100.00% 1 0 100.00%
+REPORT_ARCHIVE: obj2.c 1 0 100.00% 1 0 100.00% 1 0 100.00%
+REPORT_ARCHIVE: TOTAL 2 0 100.00% 2 0 100.00% 2 0 100.00%




More information about the llvm-commits mailing list