From ba70a3842315fcdffab941bb54f3eaac57d29181 Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Wed, 11 Mar 2015 02:30:51 +0000 Subject: [PATCH] InstrProf: Teach llvm-cov to handle universal binaries when given -arch llvm-svn: 231902 --- include/llvm/ProfileData/CoverageMapping.h | 4 ++- .../llvm/ProfileData/CoverageMappingReader.h | 4 ++- lib/ProfileData/CoverageMapping.cpp | 5 +-- lib/ProfileData/CoverageMappingReader.cpp | 34 ++++++++++++++---- test/tools/llvm-cov/Inputs/universal-binary | Bin 0 -> 960 bytes .../llvm-cov/Inputs/universal-binary.proftext | 4 +++ test/tools/llvm-cov/universal-binary.c | 13 +++++++ tools/llvm-cov/CodeCoverage.cpp | 18 +++++++++- 8 files changed, 71 insertions(+), 11 deletions(-) create mode 100755 test/tools/llvm-cov/Inputs/universal-binary create mode 100644 test/tools/llvm-cov/Inputs/universal-binary.proftext create mode 100644 test/tools/llvm-cov/universal-binary.c diff --git a/include/llvm/ProfileData/CoverageMapping.h b/include/llvm/ProfileData/CoverageMapping.h index 08a4f5ca16a..e9d6ea5a492 100644 --- a/include/llvm/ProfileData/CoverageMapping.h +++ b/include/llvm/ProfileData/CoverageMapping.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/Triple.h" #include "llvm/ADT/iterator.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorOr.h" @@ -408,7 +409,8 @@ public: /// \brief Load the coverage mapping from the given files. static ErrorOr> - load(StringRef ObjectFilename, StringRef ProfileFilename); + load(StringRef ObjectFilename, StringRef ProfileFilename, + Triple::ArchType Arch = Triple::ArchType::UnknownArch); /// \brief The number of functions that couldn't have their profiles mapped. /// diff --git a/include/llvm/ProfileData/CoverageMappingReader.h b/include/llvm/ProfileData/CoverageMappingReader.h index 671436608ff..bc68f0b47a2 100644 --- a/include/llvm/ProfileData/CoverageMappingReader.h +++ b/include/llvm/ProfileData/CoverageMappingReader.h @@ -17,6 +17,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" #include "llvm/Object/ObjectFile.h" #include "llvm/ProfileData/CoverageMapping.h" #include "llvm/ProfileData/InstrProf.h" @@ -175,7 +176,8 @@ private: public: static ErrorOr> - create(std::unique_ptr &ObjectBuffer); + create(std::unique_ptr &ObjectBuffer, + Triple::ArchType Arch = Triple::ArchType::UnknownArch); std::error_code readNextRecord(CoverageMappingRecord &Record) override; }; diff --git a/lib/ProfileData/CoverageMapping.cpp b/lib/ProfileData/CoverageMapping.cpp index 31213d7fb2d..86b2b879904 100644 --- a/lib/ProfileData/CoverageMapping.cpp +++ b/lib/ProfileData/CoverageMapping.cpp @@ -217,12 +217,13 @@ CoverageMapping::load(CoverageMappingReader &CoverageReader, } ErrorOr> -CoverageMapping::load(StringRef ObjectFilename, StringRef ProfileFilename) { +CoverageMapping::load(StringRef ObjectFilename, StringRef ProfileFilename, + Triple::ArchType Arch) { auto CounterMappingBuff = MemoryBuffer::getFileOrSTDIN(ObjectFilename); if (std::error_code EC = CounterMappingBuff.getError()) return EC; auto CoverageReaderOrErr = - BinaryCoverageReader::create(CounterMappingBuff.get()); + BinaryCoverageReader::create(CounterMappingBuff.get(), Arch); if (std::error_code EC = CoverageReaderOrErr.getError()) return EC; auto CoverageReader = std::move(CoverageReaderOrErr.get()); diff --git a/lib/ProfileData/CoverageMappingReader.cpp b/lib/ProfileData/CoverageMappingReader.cpp index d32f1dac456..3f8f76f6094 100644 --- a/lib/ProfileData/CoverageMappingReader.cpp +++ b/lib/ProfileData/CoverageMappingReader.cpp @@ -14,6 +14,7 @@ #include "llvm/ProfileData/CoverageMappingReader.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/LEB128.h" @@ -444,11 +445,31 @@ static std::error_code loadTestingFormat(StringRef Data, static std::error_code loadBinaryFormat(MemoryBufferRef ObjectBuffer, SectionData &ProfileNames, StringRef &CoverageMapping, - uint8_t &BytesInAddress) { - auto ObjectFileOrErr = object::ObjectFile::createObjectFile(ObjectBuffer); - if (std::error_code EC = ObjectFileOrErr.getError()) + uint8_t &BytesInAddress, + Triple::ArchType Arch) { + auto BinOrErr = object::createBinary(ObjectBuffer); + if (std::error_code EC = BinOrErr.getError()) return EC; - auto OF = std::move(ObjectFileOrErr.get()); + auto Bin = std::move(BinOrErr.get()); + std::unique_ptr OF; + if (auto *Universal = dyn_cast(Bin.get())) { + // If we have a universal binary, try to look up the object for the + // appropriate architecture. + auto ObjectFileOrErr = Universal->getObjectForArch(Arch); + if (std::error_code EC = ObjectFileOrErr.getError()) + return EC; + OF = std::move(ObjectFileOrErr.get()); + } else if (isa(Bin.get())) { + // For any other object file, upcast and take ownership. + OF.reset(cast(Bin.release())); + // If we've asked for a particular arch, make sure they match. + if (Arch != Triple::ArchType::UnknownArch && OF->getArch() != Arch) + return object_error::arch_not_found; + } else + // We can only handle object files. + return instrprof_error::malformed; + + // The coverage uses native pointer sizes for the object it's written in. BytesInAddress = OF->getBytesInAddress(); // Look for the sections that we are interested in. @@ -479,7 +500,8 @@ static std::error_code loadBinaryFormat(MemoryBufferRef ObjectBuffer, } ErrorOr> -BinaryCoverageReader::create(std::unique_ptr &ObjectBuffer) { +BinaryCoverageReader::create(std::unique_ptr &ObjectBuffer, + Triple::ArchType Arch) { std::unique_ptr Reader(new BinaryCoverageReader()); SectionData Profile; @@ -492,7 +514,7 @@ BinaryCoverageReader::create(std::unique_ptr &ObjectBuffer) { BytesInAddress); else EC = loadBinaryFormat(ObjectBuffer->getMemBufferRef(), Profile, Coverage, - BytesInAddress); + BytesInAddress, Arch); if (EC) return EC; diff --git a/test/tools/llvm-cov/Inputs/universal-binary b/test/tools/llvm-cov/Inputs/universal-binary new file mode 100755 index 0000000000000000000000000000000000000000..d566df95e4ce709ba45619c4f093aecce2065bb9 GIT binary patch literal 960 zcmbtTy-EW?5T4VhF-A%eGDYy4%M8Q|5y64)X1|%)Z+B<7*WuGM5m^?|0{kps!#&8F-Uc5-BrHzM z1Is{vhUktGSP`uQJ;0bku2|s6PfPN~F;mWm%>g(!Fk_nKPE!b6SWow9MVM2Bx|(Cp z_v!=2WHW^fM@FXmic`2Y0Z$Cfm}<4{no_OpIzA%P^vwIV@~sDC%J51X3!NKTk67`->JRl5}vCKtO4V3CtYjtST>2e2k?J2 z?jLKZ^>Cjk$P%Ev(%gUi1~&6KpGRK_>+vvkdvg`7z4ZJo#1bqViv`$G&N0|Fz#seMj-;8_4vsjTLog2?_QDW?@)%~XH@3*{4yIgNL)xC>~=hUy$B?wrS Zl_b6>%ylZ>Xf^r{-sAkc#5HEi;u{l%N1*@! literal 0 HcmV?d00001 diff --git a/test/tools/llvm-cov/Inputs/universal-binary.proftext b/test/tools/llvm-cov/Inputs/universal-binary.proftext new file mode 100644 index 00000000000..97816c29f36 --- /dev/null +++ b/test/tools/llvm-cov/Inputs/universal-binary.proftext @@ -0,0 +1,4 @@ +main +0x0 +1 +100 diff --git a/test/tools/llvm-cov/universal-binary.c b/test/tools/llvm-cov/universal-binary.c new file mode 100644 index 00000000000..7fe2fe86243 --- /dev/null +++ b/test/tools/llvm-cov/universal-binary.c @@ -0,0 +1,13 @@ +// The coverage reader should be able to handle universal binaries + +//CHECK: 100| @[[LINE+1]]| int main +int main(int argc, const char *argv[]) {} + +// RUN: llvm-profdata merge %S/Inputs/universal-binary.proftext -o %t.profdata +// RUN: llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -no-colors -filename-equivalence %s -arch x86_64 | FileCheck %s + +// RUN: not llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -no-colors -filename-equivalence %s -arch i386 2>&1 | FileCheck --check-prefix=WRONG-ARCH %s +// WRONG-ARCH: Failed to load coverage + +// llvm-cov doesn't work on big endian yet +// XFAIL: powerpc64-, s390x, mips-, mips64-, sparc diff --git a/tools/llvm-cov/CodeCoverage.cpp b/tools/llvm-cov/CodeCoverage.cpp index cf8ab337797..b4a05843311 100644 --- a/tools/llvm-cov/CodeCoverage.cpp +++ b/tools/llvm-cov/CodeCoverage.cpp @@ -20,6 +20,7 @@ #include "SourceCoverageView.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" #include "llvm/ProfileData/CoverageMapping.h" #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/CommandLine.h" @@ -87,6 +88,7 @@ public: LoadedSourceFiles; bool CompareFilenamesOnly; StringMap RemappedFilenames; + llvm::Triple::ArchType CoverageArch; }; } @@ -193,7 +195,8 @@ CodeCoverageTool::createSourceFileView(StringRef SourceFile, } std::unique_ptr CodeCoverageTool::load() { - auto CoverageOrErr = CoverageMapping::load(ObjectFilename, PGOFilename); + auto CoverageOrErr = CoverageMapping::load(ObjectFilename, PGOFilename, + CoverageArch); if (std::error_code EC = CoverageOrErr.getError()) { colored_ostream(errs(), raw_ostream::RED) << "error: Failed to load coverage: " << EC.message(); @@ -242,6 +245,9 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { cl::desc( "File with the profile data obtained after an instrumented run")); + cl::opt Arch( + "arch", cl::desc("architecture of the coverage mapping binary")); + cl::opt DebugDump("dump", cl::Optional, cl::desc("Show internal debug dump")); @@ -322,6 +328,16 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { Filters.push_back(std::unique_ptr(StatFilterer)); } + if (Arch.empty()) + CoverageArch = llvm::Triple::ArchType::UnknownArch; + else { + CoverageArch = Triple(Arch).getArch(); + if (CoverageArch == llvm::Triple::ArchType::UnknownArch) { + errs() << "error: Unknown architecture: " << Arch << "\n"; + return 1; + } + } + for (const auto &File : InputSourceFiles) { SmallString<128> Path(File); if (!CompareFilenamesOnly)