From 34a34aa89ea19bcdb193cc0ab4a859c878ebb57b Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Mon, 8 Feb 2016 22:49:40 +0000 Subject: [PATCH] llvm-cov: Fix reading gcov data that does not have function names In order for recent gcov versions to read the coverage data, you have to use UseCfgChecksum=true and FunctionNamesInData=false options for coverage profiling pass. This is because gcov is expecting the function section in .gcda to be exactly 3 words in size, containing ident and two checksums. While llvm-cov is compatible with UseCfgChecksum=true, it always expects a function name in .gcda function sections (it's not compatible with FunctionNamesInData=false). Thus it's currently impossible to generate one set of coverage files that works with both gcov and llvm-cov. This change fixes the reading of coverage information to only read the function name if it's present. Patch by Arseny Kapoulkine. Thanks! llvm-svn: 260162 --- llvm/lib/IR/GCOV.cpp | 22 ++++++++------- .../llvm-cov/Inputs/gcov47_compatibility.gcda | Bin 0 -> 116 bytes .../llvm-cov/Inputs/gcov47_compatibility.gcno | Bin 0 -> 228 bytes llvm/test/tools/llvm-cov/gcov47_compatibility.cpp | 30 +++++++++++++++++++++ 4 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 llvm/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcda create mode 100644 llvm/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcno create mode 100644 llvm/test/tools/llvm-cov/gcov47_compatibility.cpp diff --git a/llvm/lib/IR/GCOV.cpp b/llvm/lib/IR/GCOV.cpp index 5cce962..a9f7f45 100644 --- a/llvm/lib/IR/GCOV.cpp +++ b/llvm/lib/IR/GCOV.cpp @@ -248,10 +248,12 @@ bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { /// readGCDA - Read a function from the GCDA buffer. Return false if an error /// occurs. bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { - uint32_t Dummy; - if (!Buff.readInt(Dummy)) + uint32_t HeaderLength; + if (!Buff.readInt(HeaderLength)) return false; // Function header length + uint64_t EndPos = Buff.getCursor() + HeaderLength * sizeof(uint32_t); + uint32_t GCDAIdent; if (!Buff.readInt(GCDAIdent)) return false; @@ -281,13 +283,15 @@ bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { } } - StringRef GCDAName; - if (!Buff.readString(GCDAName)) - return false; - if (Name != GCDAName) { - errs() << "Function names do not match: " << Name << " != " << GCDAName - << ".\n"; - return false; + if (Buff.getCursor() < EndPos) { + StringRef GCDAName; + if (!Buff.readString(GCDAName)) + return false; + if (Name != GCDAName) { + errs() << "Function names do not match: " << Name << " != " << GCDAName + << ".\n"; + return false; + } } if (!Buff.readArcTag()) { diff --git a/llvm/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcda b/llvm/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcda new file mode 100644 index 0000000000000000000000000000000000000000..825156ba63a45a02118805bc03a981f4c2277c15 GIT binary patch literal 116 zcmYdHNlw=?H!$%!@z05Yfq{`3NPs|BTeBEMY#}2Hkk1GfMbJR*LQbd{h=R!@2_Z8V GBXa=6H42;n literal 0 HcmV?d00001 diff --git a/llvm/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcno b/llvm/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcno new file mode 100644 index 0000000000000000000000000000000000000000..90e3bd277a941bb17398f3b772b87151638a235d GIT binary patch literal 228 zcmd1LOHS7^H!$%!@z05Yfq{`9NPs|BTeBEQj0wojP0Y*#iLnE5dUAf5iFtf-er`cx zNoG=JPG(7^UUESJNL~^|FgP+YgK1>K87{^M7lw#|_#itVz!k0zCc?nr%E$}k!1NJv KgA_s|oCN^0p&sr4 literal 0 HcmV?d00001 diff --git a/llvm/test/tools/llvm-cov/gcov47_compatibility.cpp b/llvm/test/tools/llvm-cov/gcov47_compatibility.cpp new file mode 100644 index 0000000..02f8d78 --- /dev/null +++ b/llvm/test/tools/llvm-cov/gcov47_compatibility.cpp @@ -0,0 +1,30 @@ +// Make sure that llvm-cov can read coverage data written in gcov47+ compatible +// format. + +// Compile with these arguments and run the result to generate .gc* files: +// -coverage -Xclang -coverage-no-function-names-in-data +// -Xclang -coverage-cfg-checksum -Xclang -coverage-version='407*' + +// We need shell for cd +// REQUIRES: shell + +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: cd %t +// RUN: cp %s %p/Inputs/gcov47_compatibility.gc* . + +// RUN: llvm-cov gcov gcov47_compatibility.cpp | FileCheck %s --check-prefix=STDOUT +// STDOUT: File 'gcov47_compatibility.cpp' +// STDOUT: Lines executed:100.00% of 1 +// STDOUT: gcov47_compatibility.cpp:creating 'gcov47_compatibility.cpp.gcov' + +// RUN: FileCheck %s --check-prefix=GCOV < %t/gcov47_compatibility.cpp.gcov +// GCOV: -: 0:Runs:1 +// GCOV: -: 0:Programs:1 + +int main(int argc, const char *argv[]) { // GCOV: -: [[@LINE]]:int main( + return 0; // GCOV: 1: [[@LINE]]: return +} // GCOV: -: [[@LINE]]:} + +// llvm-cov doesn't work on big endian yet +// XFAIL: powerpc64-, s390x, mips-, mips64-, sparc -- 2.7.4