[llvm] r195191 - llvm-cov: Added file checksum to gcno and gcda files.

Yuchen Wu yuchenericwu at hotmail.com
Tue Nov 19 20:15:05 PST 2013


Author: ywu
Date: Tue Nov 19 22:15:05 2013
New Revision: 195191

URL: http://llvm.org/viewvc/llvm-project?rev=195191&view=rev
Log:
llvm-cov: Added file checksum to gcno and gcda files.

Instead of permanently outputting "MVLL" as the file checksum, clang
will create gcno and gcda checksums by hashing the destination block
numbers of every arc. This allows for llvm-cov to check if the two gcov
files are synchronized.

Regenerated the test files so they contain the checksum. Also added
negative test to ensure error when the checksums don't match.

Added:
    llvm/trunk/test/tools/llvm-cov/Inputs/test_checksum_mismatch.gcda
      - copied, changed from r195189, llvm/trunk/test/tools/llvm-cov/Inputs/test.gcda
Modified:
    llvm/trunk/include/llvm/Support/GCOV.h
    llvm/trunk/lib/IR/GCOV.cpp
    llvm/trunk/lib/Transforms/Instrumentation/GCOVProfiling.cpp
    llvm/trunk/test/Transforms/GCOVProfiling/version.ll
    llvm/trunk/test/tools/llvm-cov/Inputs/test.gcda
    llvm/trunk/test/tools/llvm-cov/Inputs/test.gcno
    llvm/trunk/test/tools/llvm-cov/Inputs/test_read_fail.gcno
    llvm/trunk/test/tools/llvm-cov/llvm-cov.test

Modified: llvm/trunk/include/llvm/Support/GCOV.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/GCOV.h?rev=195191&r1=195190&r2=195191&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/GCOV.h (original)
+++ llvm/trunk/include/llvm/Support/GCOV.h Tue Nov 19 22:15:05 2013
@@ -45,15 +45,15 @@ public:
   
   /// readGCOVFormat - Read GCOV signature at the beginning of buffer.
   GCOV::GCOVFormat readGCOVFormat() {
-    StringRef Magic = Buffer->getBuffer().slice(0, 12);
-    Cursor = 12;
-    if (Magic == "oncg*404MVLL")
+    StringRef Magic = Buffer->getBuffer().slice(0, 8);
+    Cursor = 8;
+    if (Magic == "oncg*404")
       return GCOV::GCNO_404;
-    else if (Magic == "oncg*204MVLL")
+    else if (Magic == "oncg*204")
       return GCOV::GCNO_402;
-    else if (Magic == "adcg*404MVLL")
+    else if (Magic == "adcg*404")
       return GCOV::GCDA_404;
-    else if (Magic == "adcg*204MVLL")
+    else if (Magic == "adcg*204")
       return GCOV::GCDA_402;
     
     Cursor = 0;
@@ -193,12 +193,13 @@ private:
 /// (.gcno and .gcda).
 class GCOVFile {
 public:
-  GCOVFile() : Functions(), RunCount(0), ProgramCount(0) {}
+  GCOVFile() : Checksum(0), Functions(), RunCount(0), ProgramCount(0) {}
   ~GCOVFile();
   bool read(GCOVBuffer &Buffer);
   void dump() const;
   void collectLineCounts(FileInfo &FI);
 private:
+  uint32_t Checksum;
   SmallVector<GCOVFunction *, 16> Functions;
   uint32_t RunCount;
   uint32_t ProgramCount;

Modified: llvm/trunk/lib/IR/GCOV.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/GCOV.cpp?rev=195191&r1=195190&r2=195191&view=diff
==============================================================================
--- llvm/trunk/lib/IR/GCOV.cpp (original)
+++ llvm/trunk/lib/IR/GCOV.cpp Tue Nov 19 22:15:05 2013
@@ -46,6 +46,7 @@ bool GCOVFile::read(GCOVBuffer &Buffer)
     return false;
 
   if (isGCNOFile(Format)) {
+    if (!Buffer.readInt(Checksum)) return false;
     while (true) {
       if (!Buffer.readFunctionTag()) break;
       GCOVFunction *GFun = new GCOVFunction();
@@ -55,6 +56,12 @@ bool GCOVFile::read(GCOVBuffer &Buffer)
     }
   }
   else if (isGCDAFile(Format)) {
+    uint32_t Checksum2;
+    if (!Buffer.readInt(Checksum2)) return false;
+    if (Checksum != Checksum2) {
+      errs() << "File checksum does not match.\n";
+      return false;
+    }
     for (size_t i = 0, e = Functions.size(); i < e; ++i) {
       if (!Buffer.readFunctionTag()) {
         errs() << "Unexpected number of functions.\n";

Modified: llvm/trunk/lib/Transforms/Instrumentation/GCOVProfiling.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/GCOVProfiling.cpp?rev=195191&r1=195190&r2=195191&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/GCOVProfiling.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/GCOVProfiling.cpp Tue Nov 19 22:15:05 2013
@@ -18,6 +18,7 @@
 
 #include "llvm/Transforms/Instrumentation.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
@@ -62,20 +63,28 @@ GCOVOptions GCOVOptions::getDefault() {
 }
 
 namespace {
+  class GCOVFunction;
+
   class GCOVProfiler : public ModulePass {
   public:
     static char ID;
     GCOVProfiler() : ModulePass(ID), Options(GCOVOptions::getDefault()) {
-      ReversedVersion[0] = Options.Version[3];
-      ReversedVersion[1] = Options.Version[2];
-      ReversedVersion[2] = Options.Version[1];
-      ReversedVersion[3] = Options.Version[0];
-      ReversedVersion[4] = '\0';
-      initializeGCOVProfilerPass(*PassRegistry::getPassRegistry());
+      init();
     }
     GCOVProfiler(const GCOVOptions &Options) : ModulePass(ID), Options(Options){
       assert((Options.EmitNotes || Options.EmitData) &&
              "GCOVProfiler asked to do nothing?");
+      init();
+    }
+    ~GCOVProfiler() {
+      DeleteContainerPointers(Funcs);
+    }
+    virtual const char *getPassName() const {
+      return "GCOV Profiler";
+    }
+
+  private:
+    void init() {
       ReversedVersion[0] = Options.Version[3];
       ReversedVersion[1] = Options.Version[2];
       ReversedVersion[2] = Options.Version[1];
@@ -83,11 +92,6 @@ namespace {
       ReversedVersion[4] = '\0';
       initializeGCOVProfilerPass(*PassRegistry::getPassRegistry());
     }
-    virtual const char *getPassName() const {
-      return "GCOV Profiler";
-    }
-
-  private:
     bool runOnModule(Module &M);
 
     // Create the .gcno files for the Module based on DebugInfo.
@@ -131,9 +135,12 @@ namespace {
 
     // Reversed, NUL-terminated copy of Options.Version.
     char ReversedVersion[5];  
+    // Checksum, produced by hash of EdgeDestinations
+    uint32_t FileChecksum;
 
     Module *M;
     LLVMContext *Ctx;
+    SmallVector<GCOVFunction *, 16> Funcs;
   };
 }
 
@@ -145,7 +152,7 @@ ModulePass *llvm::createGCOVProfilerPass
   return new GCOVProfiler(Options);
 }
 
-static std::string getFunctionName(DISubprogram SP) {
+static StringRef getFunctionName(DISubprogram SP) {
   if (!SP.getLinkageName().empty())
     return SP.getLinkageName();
   return SP.getName();
@@ -302,7 +309,8 @@ namespace {
   class GCOVFunction : public GCOVRecord {
    public:
     GCOVFunction(DISubprogram SP, raw_ostream *os, uint32_t Ident,
-                 bool UseCfgChecksum) {
+                 bool UseCfgChecksum) :
+        SP(SP), Ident(Ident), UseCfgChecksum(UseCfgChecksum), CfgChecksum(0) {
       this->os = os;
 
       Function *F = SP.getFunction();
@@ -312,20 +320,6 @@ namespace {
         Blocks[BB] = new GCOVBlock(i++, os);
       }
       ReturnBlock = new GCOVBlock(i++, os);
-
-      writeBytes(FunctionTag, 4);
-      uint32_t BlockLen = 1 + 1 + 1 + lengthOfGCOVString(getFunctionName(SP)) +
-          1 + lengthOfGCOVString(SP.getFilename()) + 1;
-      if (UseCfgChecksum)
-        ++BlockLen;
-      write(BlockLen);
-      write(Ident);
-      write(0);  // lineno checksum
-      if (UseCfgChecksum)
-        write(0);  // cfg checksum
-      writeGCOVString(getFunctionName(SP));
-      writeGCOVString(SP.getFilename());
-      write(SP.getLineNumber());
     }
 
     ~GCOVFunction() {
@@ -341,7 +335,37 @@ namespace {
       return *ReturnBlock;
     }
 
+    std::string getEdgeDestinations() {
+      std::string EdgeDestinations;
+      raw_string_ostream EDOS(EdgeDestinations);
+      Function *F = Blocks.begin()->first->getParent();
+      for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
+        GCOVBlock &Block = *Blocks[I];
+        for (int i = 0, e = Block.OutEdges.size(); i != e; ++i)
+          EDOS << Block.OutEdges[i]->Number;
+      }
+      return EdgeDestinations;
+    }
+
+    void setCfgChecksum(uint32_t Checksum) {
+      CfgChecksum = Checksum;
+    }
+
     void writeOut() {
+      writeBytes(FunctionTag, 4);
+      uint32_t BlockLen = 1 + 1 + 1 + lengthOfGCOVString(getFunctionName(SP)) +
+          1 + lengthOfGCOVString(SP.getFilename()) + 1;
+      if (UseCfgChecksum)
+        ++BlockLen;
+      write(BlockLen);
+      write(Ident);
+      write(0);  // lineno checksum
+      if (UseCfgChecksum)
+        write(CfgChecksum);
+      writeGCOVString(getFunctionName(SP));
+      writeGCOVString(SP.getFilename());
+      write(SP.getLineNumber());
+
       // Emit count of blocks.
       writeBytes(BlockTag, 4);
       write(Blocks.size() + 1);
@@ -375,6 +399,10 @@ namespace {
     }
 
    private:
+    DISubprogram SP;
+    uint32_t Ident;
+    bool UseCfgChecksum;
+    uint32_t CfgChecksum;
     DenseMap<BasicBlock *, GCOVBlock *> Blocks;
     GCOVBlock *ReturnBlock;
   };
@@ -427,9 +455,7 @@ void GCOVProfiler::emitProfileNotes() {
     std::string ErrorInfo;
     raw_fd_ostream out(mangleName(CU, "gcno").c_str(), ErrorInfo,
                        sys::fs::F_Binary);
-    out.write("oncg", 4);
-    out.write(ReversedVersion, 4);
-    out.write("MVLL", 4);
+    std::string EdgeDestinations;
 
     DIArray SPs = CU.getSubprograms();
     for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) {
@@ -441,17 +467,19 @@ void GCOVProfiler::emitProfileNotes() {
 
       Function *F = SP.getFunction();
       if (!F) continue;
-      GCOVFunction Func(SP, &out, i, Options.UseCfgChecksum);
+      GCOVFunction *Func =
+        new GCOVFunction(SP, &out, i, Options.UseCfgChecksum);
+      Funcs.push_back(Func);
 
       for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
-        GCOVBlock &Block = Func.getBlock(BB);
+        GCOVBlock &Block = Func->getBlock(BB);
         TerminatorInst *TI = BB->getTerminator();
         if (int successors = TI->getNumSuccessors()) {
           for (int i = 0; i != successors; ++i) {
-            Block.addEdge(Func.getBlock(TI->getSuccessor(i)));
+            Block.addEdge(Func->getBlock(TI->getSuccessor(i)));
           }
         } else if (isa<ReturnInst>(TI)) {
-          Block.addEdge(Func.getReturnBlock());
+          Block.addEdge(Func->getReturnBlock());
         }
 
         uint32_t Line = 0;
@@ -467,8 +495,18 @@ void GCOVProfiler::emitProfileNotes() {
           Lines.addLine(Loc.getLine());
         }
       }
-      Func.writeOut();
+      EdgeDestinations += Func->getEdgeDestinations();
     }
+
+    FileChecksum = hash_value(EdgeDestinations);
+    out.write("oncg", 4);
+    out.write(ReversedVersion, 4);
+    out.write(reinterpret_cast<char*>(&FileChecksum), 4);
+
+    for (SmallVectorImpl<GCOVFunction *>::iterator I = Funcs.begin(),
+           E = Funcs.end(); I != E; ++I)
+      (*I)->writeOut();
+
     out.write("\0\0\0\0\0\0\0\0", 8);  // EOF
     out.close();
   }
@@ -666,6 +704,7 @@ Constant *GCOVProfiler::getStartFileFunc
   Type *Args[] = {
     Type::getInt8PtrTy(*Ctx),  // const char *orig_filename
     Type::getInt8PtrTy(*Ctx),  // const char version[4]
+    Type::getInt32Ty(*Ctx),    // uint32_t checksum
   };
   FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
   return M->getOrInsertFunction("llvm_gcda_start_file", FTy);
@@ -683,10 +722,11 @@ Constant *GCOVProfiler::getIncrementIndi
 }
 
 Constant *GCOVProfiler::getEmitFunctionFunc() {
-  Type *Args[3] = {
+  Type *Args[] = {
     Type::getInt32Ty(*Ctx),    // uint32_t ident
     Type::getInt8PtrTy(*Ctx),  // const char *function_name
     Type::getInt8Ty(*Ctx),     // uint8_t use_extra_checksum
+    Type::getInt32Ty(*Ctx),    // uint32_t cfg_checksum
   };
   FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
   return M->getOrInsertFunction("llvm_gcda_emit_function", FTy);
@@ -760,17 +800,19 @@ Function *GCOVProfiler::insertCounterWri
     for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
       DICompileUnit CU(CU_Nodes->getOperand(i));
       std::string FilenameGcda = mangleName(CU, "gcda");
-      Builder.CreateCall2(StartFile,
+      Builder.CreateCall3(StartFile,
                           Builder.CreateGlobalStringPtr(FilenameGcda),
-                          Builder.CreateGlobalStringPtr(ReversedVersion));
+                          Builder.CreateGlobalStringPtr(ReversedVersion),
+                          Builder.getInt32(FileChecksum));
       for (unsigned j = 0, e = CountersBySP.size(); j != e; ++j) {
         DISubprogram SP(CountersBySP[j].second);
-        Builder.CreateCall3(
+        Builder.CreateCall4(
             EmitFunction, Builder.getInt32(j),
             Options.FunctionNamesInData ?
               Builder.CreateGlobalStringPtr(getFunctionName(SP)) :
               Constant::getNullValue(Builder.getInt8PtrTy()),
-            Builder.getInt8(Options.UseCfgChecksum));
+            Builder.getInt8(Options.UseCfgChecksum),
+            Builder.getInt32(FileChecksum));
 
         GlobalVariable *GV = CountersBySP[j].first;
         unsigned Arcs =

Modified: llvm/trunk/test/Transforms/GCOVProfiling/version.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GCOVProfiling/version.ll?rev=195191&r1=195190&r2=195191&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/GCOVProfiling/version.ll (original)
+++ llvm/trunk/test/Transforms/GCOVProfiling/version.ll Tue Nov 19 22:15:05 2013
@@ -1,11 +1,11 @@
 ; RUN: echo '!9 = metadata !{metadata !"%T/version.ll", metadata !0}' > %t1
 ; RUN: cat %s %t1 > %t2
 ; RUN: opt -insert-gcov-profiling -disable-output < %t2
-; RUN: head -c12 %T/version.gcno | grep '^oncg\*204MVLL$'
+; RUN: head -c8 %T/version.gcno | grep '^oncg\*204'
 ; RUN: rm %T/version.gcno
 ; RUN: not opt -insert-gcov-profiling -default-gcov-version=asdfasdf -disable-output < %t2
 ; RUN: opt -insert-gcov-profiling -default-gcov-version=407* -disable-output < %t2
-; RUN: head -c12 %T/version.gcno | grep '^oncg\*704MVLL$'
+; RUN: head -c8 %T/version.gcno | grep '^oncg\*704'
 ; RUN: rm %T/version.gcno
 
 define void @test() {

Modified: llvm/trunk/test/tools/llvm-cov/Inputs/test.gcda
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/test.gcda?rev=195191&r1=195190&r2=195191&view=diff
==============================================================================
Binary files llvm/trunk/test/tools/llvm-cov/Inputs/test.gcda (original) and llvm/trunk/test/tools/llvm-cov/Inputs/test.gcda Tue Nov 19 22:15:05 2013 differ

Modified: llvm/trunk/test/tools/llvm-cov/Inputs/test.gcno
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/test.gcno?rev=195191&r1=195190&r2=195191&view=diff
==============================================================================
Binary files llvm/trunk/test/tools/llvm-cov/Inputs/test.gcno (original) and llvm/trunk/test/tools/llvm-cov/Inputs/test.gcno Tue Nov 19 22:15:05 2013 differ

Copied: llvm/trunk/test/tools/llvm-cov/Inputs/test_checksum_mismatch.gcda (from r195189, llvm/trunk/test/tools/llvm-cov/Inputs/test.gcda)
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/test_checksum_mismatch.gcda?p2=llvm/trunk/test/tools/llvm-cov/Inputs/test_checksum_mismatch.gcda&p1=llvm/trunk/test/tools/llvm-cov/Inputs/test.gcda&r1=195189&r2=195191&rev=195191&view=diff
==============================================================================
Binary files llvm/trunk/test/tools/llvm-cov/Inputs/test.gcda (original) and llvm/trunk/test/tools/llvm-cov/Inputs/test_checksum_mismatch.gcda Tue Nov 19 22:15:05 2013 differ

Modified: llvm/trunk/test/tools/llvm-cov/Inputs/test_read_fail.gcno
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/test_read_fail.gcno?rev=195191&r1=195190&r2=195191&view=diff
==============================================================================
Binary files llvm/trunk/test/tools/llvm-cov/Inputs/test_read_fail.gcno (original) and llvm/trunk/test/tools/llvm-cov/Inputs/test_read_fail.gcno Tue Nov 19 22:15:05 2013 differ

Modified: llvm/trunk/test/tools/llvm-cov/llvm-cov.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/llvm-cov.test?rev=195191&r1=195190&r2=195191&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/llvm-cov.test (original)
+++ llvm/trunk/test/tools/llvm-cov/llvm-cov.test Tue Nov 19 22:15:05 2013
@@ -7,4 +7,6 @@ RUN:   | diff -aub test.cpp.gcov -
 
 RUN: not llvm-cov -gcno=test_read_fail.gcno -gcda=test.gcda
 
+RUN: not llvm-cov -gcno=test.gcno -gcda=test_checksum_mismatch.gcda
+
 XFAIL: powerpc64, s390x





More information about the llvm-commits mailing list