source: rtems-tools/tester/covoar/GcovFunctionData.cc @ f9a4b2c

5
Last change on this file since f9a4b2c was 100f517, checked in by Chris Johns <chrisj@…>, on 05/09/14 at 11:50:37

covoar: Merger the covoar source from rtems-testing.git.

Use waf to build covoar.

  • Property mode set to 100644
File size: 16.6 KB
Line 
1/*! @file GcovFunctionData.cc
2 *  @brief GcovFunctionData Implementation
3 *
4 *  This file contains the implementation of the class storing information
5 *  about single function.
6 */
7
8#include <stdio.h>
9#include <string.h>
10//#include <stdlib.h>
11//#include <sys/stat.h>
12
13#include "app_common.h"
14#include "GcovFunctionData.h"
15#include "ObjdumpProcessor.h"
16#include "CoverageMapBase.h"
17
18
19namespace Gcov {
20
21  GcovFunctionData::GcovFunctionData()
22  {
23    numberOfArcs = 0;
24    numberOfBlocks = 0;
25    coverageMap = NULL;
26  }
27
28  GcovFunctionData::~GcovFunctionData()
29  {
30  }
31
32  void GcovFunctionData::setChecksum( const uint32_t chk )
33  {
34    checksum = chk;
35  }
36
37  void GcovFunctionData::setId( const uint32_t idNumber )
38  {
39    id = idNumber;
40  }
41
42
43  void GcovFunctionData::setFirstLineNumber( const uint32_t lineNo )
44  {
45    firstLineNumber = lineNo;
46  }
47
48  bool GcovFunctionData::setFunctionName( const char* fcnName )
49  {
50    std::string         symbolName;
51
52    symbolName = fcnName;
53
54    if ( strlen(fcnName) >= FUNCTION_NAME_LENGTH ) {
55      fprintf(
56        stderr,
57        "ERROR: Function name is too long to be correctly stored: %u\n",
58        (unsigned int) strlen(fcnName)
59      );
60      return false;
61    }
62
63    strcpy (functionName, fcnName);
64
65    // Tie function to its coverage map
66    symbolInfo = SymbolsToAnalyze->find( symbolName );
67    if ( symbolInfo != NULL )
68      coverageMap = symbolInfo->unifiedCoverageMap;
69
70#if 0
71    if ( coverageMap == NULL) {
72      fprintf(
73        stderr,
74        "ERROR: Could not find coverage map for: %s\n",
75        symbolName.c_str()
76      );
77    } else {
78      fprintf(
79        stderr,
80        "SUCCESS: Hound coverage map for: %s\n",
81        symbolName.c_str()
82      );
83   }
84#endif
85
86    return true;
87  }
88
89  bool GcovFunctionData::setFileName( const char* fileName ) {
90    if ( strlen(fileName) >= FILE_NAME_LENGTH ){
91      fprintf(
92        stderr,
93        "ERROR: File name is too long to be correctly stored: %u\n",
94        (unsigned int) strlen(fileName)
95      );
96      return false;
97    }
98    strcpy (sourceFileName, fileName);
99    return true;
100  }
101
102  arcs_t GcovFunctionData::getArcs() const
103  {
104    return arcs;
105  }
106
107  uint32_t GcovFunctionData::getChecksum() const
108  {
109    return checksum;
110  }
111
112  uint32_t GcovFunctionData::getId() const
113  {
114    return id;
115  }
116
117  void GcovFunctionData::getCounters(
118    uint64_t* counterValues,
119    uint32_t &countersFound,
120    uint64_t &countersSum,
121    uint64_t &countersMax
122  )
123  {
124    arcs_iterator_t     currentArc;
125    int                 i;
126
127    countersFound       = 0;
128    countersSum         = 0;
129    countersMax         = 0;
130
131    // Locate relevant counters and copy their values
132    i = 0;
133    for(
134      currentArc = arcs.begin();
135      currentArc != arcs.end();
136      currentArc++
137    )
138    {
139      if ( currentArc->flags == 0 || currentArc->flags == 2 ||
140           currentArc->flags == 4 ) {
141        countersFound++;
142        countersSum += currentArc->counter;
143        counterValues[i] = currentArc->counter;
144        if ( countersMax <= currentArc->counter)
145          countersMax = currentArc->counter;
146        i++;
147      }
148    }
149  }
150
151  blocks_t GcovFunctionData::getBlocks() const
152  {
153    return blocks;
154  }
155
156  void GcovFunctionData::addArc(
157    uint32_t  source,
158    uint32_t  destination,
159    uint32_t  flags
160  )
161  {
162    gcov_arc_info arc;
163
164    numberOfArcs++;
165    arc.sourceBlock = source;
166    arc.destinationBlock = destination;
167    arc.flags = flags;
168    arc.counter = 0;
169    arcs.push_back(arc);
170  }
171
172  void GcovFunctionData::addBlock(
173    const uint32_t              id,
174    const uint32_t              flags,
175    const char *                sourceFileName
176  )
177  {
178    gcov_block_info block;
179    numberOfBlocks++;
180    block.id    = id;
181    block.flags = flags;
182    block.numberOfLines = 0;
183    block.counter = 0;
184    strcpy (block.sourceFileName, sourceFileName);
185    blocks.push_back(block);
186  }
187
188  void GcovFunctionData::printFunctionInfo(
189    FILE * textFile,
190    uint32_t function_number
191  )
192  {
193    blocks_iterator_t  currentBlock;
194    arcs_iterator_t    currentArc;
195
196    fprintf(
197      textFile,
198      "\n\n=========================="
199      "FUNCTION %3d "
200      "==========================\n\n",
201      function_number
202    );
203    fprintf(
204      textFile,
205      "Name:      %s\n"
206      "File:      %s\n"
207      "Line:      %u\n"
208      "Id:        %u\n"
209      "Checksum:  0x%x\n\n",
210      functionName,
211      sourceFileName,
212      firstLineNumber,
213      id,
214      checksum
215    );
216
217    // Print arcs info
218    for ( currentArc = arcs.begin(); currentArc != arcs.end(); currentArc++ ) {
219      printArcInfo( textFile, currentArc );
220    }
221    fprintf( textFile, "\n");
222
223    // Print blocks info
224    for ( currentBlock = blocks.begin();
225          currentBlock != blocks.end();
226          currentBlock++
227    ) {
228      printBlockInfo( textFile, currentBlock );
229    }
230  }
231
232  void GcovFunctionData::printCoverageInfo(
233    FILE     *textFile,
234    uint32_t  function_number
235  )
236  {
237    uint32_t        baseAddress = 0;
238    uint32_t        baseSize;
239    uint32_t        currentAddress;
240    std::list<Coverage::ObjdumpProcessor::objdumpLine_t>::iterator   instruction;
241
242    if ( coverageMap != NULL ) {
243
244      for (instruction = symbolInfo->instructions.begin();
245           instruction != symbolInfo->instructions.end();
246           instruction++) {
247        if( instruction->isInstruction ) {
248          baseAddress = instruction->address;
249          break;
250        }
251      }
252      baseSize   = coverageMap->getSize();
253
254      fprintf(
255        textFile,
256        "\nInstructions (Base address: 0x%08x, Size: %4u): \n\n",
257        baseAddress,
258        baseSize
259      );
260      for ( instruction = symbolInfo->instructions.begin();
261            instruction != symbolInfo->instructions.end();
262            instruction++
263      )
264      {
265        if ( instruction->isInstruction ) {
266          currentAddress = instruction->address - baseAddress;
267          fprintf( textFile, "0x%-70s ", instruction->line.c_str() );
268          fprintf( textFile, "| 0x%08x ",   currentAddress );
269          fprintf( textFile, "*");
270          fprintf( textFile,
271                    "| exec: %4u ",
272                    coverageMap->getWasExecuted( currentAddress )
273          );
274          fprintf( textFile, "| taken/not: %4u/%4u ",
275                    coverageMap->getWasTaken( currentAddress ),
276                    coverageMap->getWasNotTaken( currentAddress )
277          );
278
279          if ( instruction->isBranch )
280            fprintf( textFile, "| Branch " );
281          else
282            fprintf( textFile, "         " );
283
284          if ( instruction->isNop )
285            fprintf( textFile, "| NOP(%3u) \n", instruction->nopSize );
286          else
287            fprintf( textFile, "           \n" );
288        }
289      }
290    }
291  }
292
293  void GcovFunctionData::setBlockFileName(
294    const blocks_iterator_t  block,
295    const char               *fileName
296  )
297  {
298    strcpy(block->sourceFileName, fileName);
299  }
300
301  void GcovFunctionData::addBlockLine(
302    const blocks_iterator_t  block,
303    const uint32_t           line
304  )
305  {
306    block->lines.push_back(line);
307    (block->numberOfLines)++;
308  }
309
310  blocks_iterator_t GcovFunctionData::findBlockById(
311    const uint32_t    id
312  )
313  {
314    blocks_iterator_t blockIterator;
315
316    if ( !blocks.empty() ) {
317      blockIterator = blocks.begin();
318      while (   blockIterator != blocks.end( ) ){
319        if ( blockIterator->id ==  id)
320          break;
321        blockIterator++;
322      }
323    } else {
324      fprintf(
325        stderr,
326        "ERROR: GcovFunctionData::findBlockById() failed, no blocks present\n"
327      );
328    }
329    return blockIterator;
330  }
331
332  void GcovFunctionData::printArcInfo(
333                FILE * textFile, arcs_iterator_t arc
334  )
335  {
336    fprintf(
337      textFile,
338      " > ARC %3u -> %3u ",
339      arc->sourceBlock,
340      arc->destinationBlock
341    );
342
343    fprintf( textFile, "\tFLAGS: ");
344    switch ( arc->flags ){
345      case 0:
346        fprintf( textFile, "( ___________ ____ _______ )");
347        break;
348      case 1:
349        fprintf( textFile, "( ___________ ____ ON_TREE )");
350        break;
351      case 2:
352        fprintf( textFile, "( ___________ FAKE _______ )");
353        break;
354      case 3:
355        fprintf( textFile, "( ___________ FAKE ON_TREE )");
356        break;
357      case 4:
358        fprintf( textFile, "( FALLTHROUGH ____ _______ )");
359        break;
360      case 5:
361        fprintf( textFile, "( FALLTHROUGH ____ ON_TREE )");
362        break;
363      default:
364        fprintf( textFile, "( =======FLAGS_ERROR====== )");
365        fprintf( stderr,
366                " ERROR: Unknown arc flag: 0x%x\n",
367                arcs.back().flags
368        );
369        break;
370    }
371    fprintf( textFile, "\tTaken: %5llu\n", (unsigned long long) arc->counter );
372  }
373
374  void GcovFunctionData::printBlockInfo(
375    FILE * textFile,
376    blocks_iterator_t block
377  )
378  {
379    std::list<uint32_t>::iterator       line;
380
381    fprintf(
382      textFile,
383      " > BLOCK %3u from %s\n"
384      "    -counter: %5llu\n"
385      "    -flags: 0x%x\n"
386      "    -lines: ",
387      block->id,
388      block->sourceFileName,
389      (unsigned long long) block->counter,
390      block->flags
391    );
392    if ( !block->lines.empty( ) )
393      for ( line = block->lines.begin() ; line != block->lines.end(); line++ )
394        fprintf ( textFile, "%u, ", *line);
395    fprintf ( textFile, "\n");
396  }
397
398  bool GcovFunctionData::processFunctionCounters( void ) {
399
400    uint32_t               baseAddress = 0;
401    uint32_t               currentAddress = 0;
402    std::list<Coverage::ObjdumpProcessor::objdumpLine_t>::iterator  instruction;
403    blocks_iterator_t      blockIterator;
404    blocks_iterator_t      blockIterator2;
405    arcs_iterator_t        arcIterator;
406    arcs_iterator_t        arcIterator2;
407    std::list<uint64_t>    taken;       // List of taken counts for branches
408    std::list<uint64_t>    notTaken;    // List of not taken counts for branches
409
410    //fprintf( stderr, "DEBUG: Processing counters for file: %s\n", sourceFileName  );
411    if ( blocks.empty() || arcs.empty() || coverageMap == NULL || symbolInfo->instructions.empty())
412    {
413      //fprintf( stderr,
414      //          "DEBUG: sanity check returned false for function: %s from file: %s\n",
415      //          functionName,
416      //          sourceFileName
417      //);
418      return false;
419    }
420
421    // Reset iterators and variables
422    blockIterator = blocks.begin();
423    arcIterator = arcs.begin();
424    arcIterator2 = arcIterator;
425    arcIterator2++;
426    instruction = symbolInfo->instructions.begin();
427    baseAddress = coverageMap->getFirstLowAddress();      //symbolInfo->baseAddress;
428    currentAddress = baseAddress;
429
430    // Find taken/not taken values for branches
431    if ( !processBranches( &taken , &notTaken ) )
432    {
433      //fprintf( stderr,
434      //          "ERROR: Failed to process branches for function: %s from file: %s\n",
435      //          functionName,
436      //          sourceFileName
437      //);
438      return false;
439    };
440
441    // Process the branching arcs
442    while ( blockIterator != blocks.end() ) {
443      //fprintf( stderr, "DEBUG: Processing branches\n" );
444      while ( arcIterator->sourceBlock != blockIterator->id ) {
445        if ( arcIterator == arcs.end() ) {
446          //fprintf( stderr, "ERROR: Unexpectedly runned out of arcs to analyze\n" );
447          return false;
448        }
449        arcIterator++;
450        arcIterator2++;
451      }
452
453      // If no more branches break;
454      if ( arcIterator2 == arcs.end() )
455        break;
456
457      // If this is a branch without FAKE arcs process it
458      if (
459        (arcIterator->sourceBlock == arcIterator2->sourceBlock ) &&
460        !( arcIterator->flags & FAKE_ARC_FLAG ) &&
461        !( arcIterator2->flags & FAKE_ARC_FLAG )
462      ) {
463        if ( taken.empty() || notTaken.empty() ) {
464          fprintf(
465            stderr,
466            "ERROR: Branchess missing for function: %s from file: %s\n",
467            functionName,
468            sourceFileName
469          );
470          return false;
471        }
472        //fprintf( stderr, "DEBUG: Found true branching arc %3u -> %3u\n", arcIterator->sourceBlock, arcIterator->destinationBlock );
473        if ( arcIterator->flags & FALLTHROUGH_ARC_FLAG ) {
474          arcIterator->counter = notTaken.front();
475          notTaken.pop_front();
476          arcIterator2->counter = taken.front();
477          taken.pop_front();
478        } else {
479          arcIterator2->counter = notTaken.front();
480          notTaken.pop_front();
481          arcIterator->counter = taken.front();
482          taken.pop_front();                   
483        }
484
485        blockIterator2 = blocks.begin();
486        //TODO: ADD FAILSAFE
487        while ( arcIterator->destinationBlock != blockIterator2->id)   
488          blockIterator2++;
489        blockIterator2->counter += arcIterator->counter;
490 
491        blockIterator2 = blocks.begin();
492        //TODO: ADD FAILSAFE
493        while ( arcIterator2->destinationBlock != blockIterator2->id)
494            blockIterator2++;
495          blockIterator2->counter += arcIterator2->counter;
496      }     
497      blockIterator++;
498    }
499
500    // Reset iterators and variables
501    blockIterator = blocks.begin();
502    arcIterator = arcs.begin();
503    arcIterator2 = arcIterator;
504    arcIterator2++;
505
506    // Set the first block
507    blockIterator->counter = coverageMap->getWasExecuted( currentAddress );
508
509    // Analyze remaining arcs and blocks
510    while ( blockIterator != blocks.end() ) {
511      while ( arcIterator->sourceBlock != blockIterator->id ) {
512        if ( arcIterator == arcs.end() ) {
513          fprintf( stderr, "ERROR: Unexpectedly runned out of arcs to analyze\n" );
514          return false;
515        }
516        arcIterator++;
517        arcIterator2++;
518      }
519
520      // If this is the last arc, propagate counter and exit
521      if ( arcIterator2 == arcs.end() ) {
522        //fprintf( stderr,
523        //        "DEBUG: Found last arc %3u -> %3u\n",
524        //        arcIterator->sourceBlock,
525        //        arcIterator->destinationBlock
526        //);
527        arcIterator->counter = blockIterator->counter;
528        blockIterator2 =  blocks.begin();
529        while ( arcIterator->destinationBlock != blockIterator2->id)    //TODO: ADD FAILSAFE
530          blockIterator2++;
531        blockIterator2->counter += arcIterator->counter;
532        return true;
533      }
534
535      // If this is not a branch, propagate counter and continue
536      if ( arcIterator->sourceBlock != arcIterator2->sourceBlock ) {
537        //fprintf( stderr, "DEBUG: Found simple arc %3u -> %3u\n", arcIterator->sourceBlock, arcIterator->destinationBlock );
538        arcIterator->counter = blockIterator->counter;
539        blockIterator2 =  blocks.begin();;
540        while ( arcIterator->destinationBlock != blockIterator2->id)    //TODO: ADD FAILSAFE
541          blockIterator2++;
542        blockIterator2->counter += arcIterator->counter;
543      }
544           
545      // If this is  a branch with FAKE arc
546      else if ( (arcIterator->sourceBlock == arcIterator2->sourceBlock ) && ( arcIterator2->flags & FAKE_ARC_FLAG ))
547      {
548        //fprintf( stderr, "DEBUG: Found fake branching arc %3u -> %3u\n", arcIterator->sourceBlock, arcIterator->destinationBlock );
549        arcIterator->counter = blockIterator->counter;
550        blockIterator2 =  blocks.begin();
551        while ( arcIterator->destinationBlock != blockIterator2->id)    //TODO: ADD FAILSAFE
552          blockIterator2++;
553        blockIterator2->counter += arcIterator->counter;
554      }
555
556      // If this is a legitimate branch     
557      blockIterator++;
558    }
559
560    return true;
561  }
562   
563  bool GcovFunctionData::processBranches(
564            std::list<uint64_t> * taken ,
565            std::list<uint64_t> * notTaken
566  )
567  {
568    uint32_t        baseAddress = 0;
569    uint32_t        currentAddress;
570    std::list<Coverage::ObjdumpProcessor::objdumpLine_t>::iterator   instruction;
571
572    if ( coverageMap == NULL )
573      return false;
574
575    //baseAddress = coverageMap->getFirstLowAddress();      //symbolInfo->baseAddress;
576    for (instruction = symbolInfo->instructions.begin(); instruction != symbolInfo->instructions.end(); instruction++)
577      if( instruction->isInstruction ) {
578        baseAddress = instruction->address;
579        break;
580      }
581
582    //fprintf( stderr, "DEBUG: Processing instructions in search of branches\n" );
583    for (instruction = symbolInfo->instructions.begin(); instruction != symbolInfo->instructions.end(); instruction++)
584    {
585      if ( instruction->isInstruction) {
586        currentAddress = instruction-> address - baseAddress;
587        if ( instruction->isBranch ) {
588          taken->push_back ( (uint64_t) coverageMap->getWasTaken( currentAddress  ) );
589          notTaken->push_back ( (uint64_t) coverageMap->getWasNotTaken( currentAddress ) );
590          //fprintf( stderr,
591          //          "Added branch to list taken/not: %4u/%4u\n",
592          //          coverageMap->getWasTaken( currentAddress ),
593          //          coverageMap->getWasNotTaken( currentAddress )
594          //);
595        }
596      }
597    }
598    return true;
599  }
600}
601
602
Note: See TracBrowser for help on using the repository browser.