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

Last change on this file since 61410db was 61410db, checked in by Chris Johns <chrisj@…>, on Nov 28, 2018 at 9:03:29 PM

tester/coverage: Remove warnings in covoar on Windows.

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