source: rtems-testing/covoar/DesiredSymbols.cc @ a518bc5

4.11
Last change on this file since a518bc5 was a518bc5, checked in by Jennifer Averett <Jennifer.Averett@…>, on May 24, 2010 at 8:07:09 PM

2010-05-24 Jennifer Averett <Jennifer.Averett@…>

  • covoar/05_ascending.gif, covoar/05_descending.gif, covoar/05_unsorted.gif, covoar/ConfigFile.cc, covoar/ConfigFile.h, covoar/CoverageFactory.cc, covoar/CoverageFactory.h, covoar/CoverageMap.cc, covoar/CoverageMap.h, covoar/CoverageMapBase.cc, covoar/CoverageMapBase.h, covoar/CoverageRanges.cc, covoar/CoverageRanges.h, covoar/CoverageReaderBase.cc, covoar/CoverageReaderBase.h, covoar/CoverageReaderQEMU.cc, covoar/CoverageReaderQEMU.h, covoar/CoverageReaderRTEMS.cc, covoar/CoverageReaderRTEMS.h, covoar/CoverageReaderSkyeye.cc, covoar/CoverageReaderSkyeye.h, covoar/CoverageReaderTSIM.cc, covoar/CoverageReaderTSIM.h, covoar/CoverageWriterBase.cc, covoar/CoverageWriterBase.h, covoar/CoverageWriterRTEMS.cc, covoar/CoverageWriterRTEMS.h, covoar/CoverageWriterSkyeye.cc, covoar/CoverageWriterSkyeye.h, covoar/CoverageWriterTSIM.cc, covoar/CoverageWriterTSIM.h, covoar/DesiredSymbols.cc, covoar/DesiredSymbols.h, covoar/ExecutableInfo.cc, covoar/ExecutableInfo.h, covoar/Explanations.cc, covoar/Explanations.h, covoar/Makefile, covoar/ObjdumpProcessor.cc, covoar/ObjdumpProcessor.h, covoar/ReportsBase.cc, covoar/ReportsBase.h, covoar/ReportsHtml.cc, covoar/ReportsHtml.h, covoar/ReportsText.cc, covoar/ReportsText.h, covoar/SymbolTable.cc, covoar/SymbolTable.h, covoar/TargetBase.cc, covoar/TargetBase.h, covoar/TargetFactory.cc, covoar/TargetFactory.h, covoar/Target_arm.cc, covoar/Target_arm.h, covoar/Target_i386.cc, covoar/Target_i386.h, covoar/Target_lm32.cc, covoar/Target_lm32.h, covoar/Target_m68k.cc, covoar/Target_m68k.h, covoar/Target_powerpc.cc, covoar/Target_powerpc.h, covoar/Target_sparc.cc, covoar/Target_sparc.h, covoar/TraceConverter.cc, covoar/TraceList.cc, covoar/TraceList.h, covoar/TraceReaderBase.cc, covoar/TraceReaderBase.h, covoar/TraceReaderLogQEMU.cc, covoar/TraceReaderLogQEMU.h, covoar/TraceWriterBase.cc, covoar/TraceWriterBase.h, covoar/TraceWriterQEMU.cc, covoar/TraceWriterQEMU.h, covoar/app_common.cc, covoar/app_common.h, covoar/configfile_test.cc, covoar/coverage_converter.cc, covoar/covmerge.cc, covoar/covoar.cc, covoar/covoar.css, covoar/filter.gif, covoar/qemu-dump-trace.c, covoar/qemu-log.h, covoar/qemu-traces.h, covoar/rtemscov_header.h, covoar/skyeye_header.h, covoar/table.js: New files.
  • Property mode set to 100644
File size: 17.7 KB
Line 
1/*
2 *  $Id$
3 */
4
5/*! @file DesiredSymbols.cc
6 *  @brief DesiredSymbols Implementation
7 *
8 *  This file contains the implementation of the functions
9 *  which provide the functionality of the DesiredSymbols.
10 */
11
12#include <libgen.h>
13#include <limits.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17
18#include "DesiredSymbols.h"
19#include "app_common.h"
20#include "CoverageMap.h"
21#include "ObjdumpProcessor.h"
22
23namespace Coverage {
24
25  DesiredSymbols::DesiredSymbols()
26  {
27  }
28
29  DesiredSymbols::~DesiredSymbols()
30  {
31  }
32
33  void DesiredSymbols::load(
34    const char* const symbolsFile
35  )
36  {
37    #define MAX_LINE_LENGTH 512
38    char                    buffer[MAX_LINE_LENGTH];
39    char*                   cStatus;
40    bool                    done = false;
41    FILE*                   sFile;
42    SymbolInformation*      symInfo;
43    int                     line = 1;
44    std::string             symbol;
45
46    // Ensure that symbols file name is given.
47    if ( !symbolsFile ) {
48      fprintf(
49        stderr,
50        "ERROR: DesiredSymbols::load - no symbols file specified\n"
51      );
52      exit(-1);
53    }
54
55    // Open symbols file.
56    sFile = fopen( symbolsFile, "r" );
57    if ( !sFile ) {
58      fprintf(
59        stderr,
60        "ERROR: DesiredSymbols::load - unable to open symbols file %s\n",
61        symbolsFile
62      );
63      exit(-1);
64    }
65
66    // Process symbols file.
67    while ( !done ) {
68
69      symInfo = new SymbolInformation;
70
71      // Skip blank lines between symbols
72      do { 
73        buffer[0] = '\0';
74        cStatus = fgets( buffer, MAX_LINE_LENGTH, sFile );
75        if ( cStatus == NULL ) {
76          done = true;
77        }
78        else {
79          buffer[ strlen(buffer) - 1] = '\0';
80          line++;
81        }
82      } while ( !done && (buffer[0] == '\0') );
83
84      // Have we already seen this one?
85      if ( !done ) {
86        if (set.find( buffer ) != set.end()) {
87          fprintf(
88            stderr,
89            "File: %s, Line %d: Duplicate symbol: %s\n",
90            symbolsFile,
91            line,
92            buffer
93          );
94        }
95
96        // Add this to the set of symbols.
97        else {
98          set[ buffer ] = *symInfo;
99        }
100      }
101    }
102    #undef MAX_LINE_LENGTH
103  }
104
105  void DesiredSymbols::preprocess( void )
106  {
107    ObjdumpProcessor::objdumpLines_t::iterator fitr;
108    DesiredSymbols::symbolSet_t::iterator      sitr;
109    CoverageMapBase*                           theCoverageMap;
110
111    // Look at each symbol.
112    for (sitr = SymbolsToAnalyze->set.begin();
113         sitr != SymbolsToAnalyze->set.end();
114         sitr++) {
115
116      // If the unified coverage map does not exist, the symbol was
117      // never referenced by any executable.  Just skip it.
118      theCoverageMap = sitr->second.unifiedCoverageMap;
119      if (!theCoverageMap)
120        continue;
121
122      // Mark any branch instructions.
123      for (fitr = sitr->second.instructions.begin();
124           fitr != sitr->second.instructions.end();
125           fitr++) {
126        if (fitr->isBranch) {
127           theCoverageMap->setIsBranch(
128             fitr->address - sitr->second.baseAddress
129           );
130        }
131      }
132    }
133  }
134
135  void DesiredSymbols::caculateStatistics( void )
136  {
137    uint32_t                              a;
138    uint32_t                              endAddress;
139    DesiredSymbols::symbolSet_t::iterator sitr;
140    CoverageMapBase*                      theCoverageMap;
141
142    // Look at each symbol.
143    for (sitr = SymbolsToAnalyze->set.begin();
144         sitr != SymbolsToAnalyze->set.end();
145         sitr++) {
146
147      // If the unified coverage map does not exist, the symbol was
148      // never referenced by any executable.  Just skip it.
149      theCoverageMap = sitr->second.unifiedCoverageMap;
150      if (!theCoverageMap)
151        continue;
152
153      // Increment the total sizeInBytes byt the bytes in the symbol
154      stats.sizeInBytes += sitr->second.stats.sizeInBytes;
155
156      // Now scan through the coverage map of this symbol.
157      endAddress = sitr->second.stats.sizeInBytes - 1;
158      a = 0;
159      while (a <= endAddress) {
160
161        // If we are at the start of instruction increment
162        // instruction type counters as needed.
163        if ( theCoverageMap->isStartOfInstruction( a ) ) {
164
165          stats.sizeInInstructions++;
166          sitr->second.stats.sizeInInstructions++;
167
168          if (!theCoverageMap->wasExecuted( a ) ) {
169            stats.uncoveredInstructions++;
170            sitr->second.stats.uncoveredInstructions++;
171
172            if ( theCoverageMap->isBranch( a )) {
173              stats.branchesNotExecuted++;
174              sitr->second.stats.branchesNotExecuted++;
175             }
176          } else if (theCoverageMap->isBranch( a )) {
177            stats.branchesExecuted++;
178            sitr->second.stats.branchesExecuted++;
179          }
180 
181        }
182
183 
184        if (!theCoverageMap->wasExecuted( a )) {
185          stats.uncoveredBytes++;
186          sitr->second.stats.uncoveredBytes++;
187        }       
188        a++;
189
190      }
191    }
192  }
193
194
195  void DesiredSymbols::computeUncovered( void )
196  {
197    uint32_t                              a, la, ha;
198    uint32_t                              endAddress;
199    uint32_t                              count;
200    DesiredSymbols::symbolSet_t::iterator sitr;
201    CoverageRanges*                       theBranches;
202    CoverageMapBase*                      theCoverageMap;
203    CoverageRanges*                       theRanges;
204
205    // Look at each symbol.
206    for (sitr = SymbolsToAnalyze->set.begin();
207         sitr != SymbolsToAnalyze->set.end();
208         sitr++) {
209
210      // If the unified coverage map does not exist, the symbol was
211      // never referenced by any executable.  Just skip it.
212      theCoverageMap = sitr->second.unifiedCoverageMap;
213      if (!theCoverageMap)
214        continue;
215
216      // Create containers for the symbol's uncovered ranges and branches.
217      theRanges = new CoverageRanges();
218      sitr->second.uncoveredRanges = theRanges;
219      theBranches = new CoverageRanges();
220      sitr->second.uncoveredBranches = theBranches;
221
222      // Now scan through the coverage map of this symbol.
223      endAddress = sitr->second.stats.sizeInBytes - 1;
224      a = 0;
225      while (a <= endAddress) {
226       
227        // If an address was NOT executed, find consecutive unexecuted
228        // addresses and add them to the uncovered ranges.
229        if (!theCoverageMap->wasExecuted( a )) {
230
231          la = a;
232          count = 1;
233          for (ha=a+1;
234               ha<=endAddress && !theCoverageMap->wasExecuted( ha );
235               ha++)
236          {
237            if ( theCoverageMap->isStartOfInstruction( ha ) )
238              count++;
239          }
240          ha--;
241
242          stats.uncoveredRanges++;
243          sitr->second.stats.uncoveredRanges++;
244          theRanges->add(
245            sitr->second.baseAddress + la,
246            sitr->second.baseAddress + ha,
247            CoverageRanges::UNCOVERED_REASON_NOT_EXECUTED,
248            count
249          );
250          a = ha + 1;
251        }
252
253        // If an address is a branch instruction, add any uncovered branches
254        // to the uncoverd branches.
255        else if (theCoverageMap->isBranch( a )) {
256          la = a;
257          for (ha=a+1;
258               ha<=endAddress && !theCoverageMap->isStartOfInstruction( ha );
259               ha++)
260            ;
261          ha--;
262
263          if (theCoverageMap->wasAlwaysTaken( la )) {
264            stats.branchesAlwaysTaken++;
265            sitr->second.stats.branchesAlwaysTaken++;
266            theBranches->add(
267              sitr->second.baseAddress + la,
268              sitr->second.baseAddress + ha,
269              CoverageRanges::UNCOVERED_REASON_BRANCH_ALWAYS_TAKEN,
270              1
271            );
272            if (Verbose)
273              fprintf(
274                stderr,
275                "Branch always taken found in %s (0x%x - 0x%x)\n",
276                (sitr->first).c_str(),
277                sitr->second.baseAddress + la,
278                sitr->second.baseAddress + ha
279              );
280          }
281
282          else if (theCoverageMap->wasNeverTaken( la )) {
283            stats.branchesNeverTaken++;
284            sitr->second.stats.branchesNeverTaken++;
285            theBranches->add(
286              sitr->second.baseAddress + la,
287              sitr->second.baseAddress + ha,
288              CoverageRanges::UNCOVERED_REASON_BRANCH_NEVER_TAKEN,
289              1
290            );
291            if (Verbose)
292              fprintf(
293                stderr,
294                "Branch never taken found in %s (0x%x - 0x%x)\n",
295                (sitr->first).c_str(),
296                sitr->second.baseAddress + la,
297                sitr->second.baseAddress + ha
298              );
299          }
300          a = ha + 1;
301        }
302        else
303          a++;
304      }
305    }
306  }
307
308
309  void DesiredSymbols::createCoverageMap(
310    const std::string& symbolName,
311    uint32_t           size
312  )
313  {
314    CoverageMapBase*      aCoverageMap;
315    uint32_t              highAddress;
316    symbolSet_t::iterator itr;
317
318    // Ensure that the symbol is a desired symbol.
319    itr = set.find( symbolName );
320
321    if (itr == set.end()) {
322
323      fprintf(
324        stderr,
325        "ERROR: DesiredSymbols::createCoverageMap - Unable to create "
326        "unified coverage map for %s because it is NOT a desired symbol\n",
327        symbolName.c_str()
328      );
329      exit( -1 );
330    }
331
332    // If we have already created a coverage map, ...
333    if (itr->second.unifiedCoverageMap) {
334
335      // ensure that the specified size matches the existing size.
336      if (itr->second.stats.sizeInBytes != size) {
337
338        fprintf(
339          stderr,
340          "ERROR: DesiredSymbols::createCoverageMap - Attempt to create "
341          "unified coverage maps for %s with different sizes\n",
342          symbolName.c_str()
343        );
344        exit( -1 );
345      }
346    }
347
348    // If we don't already have a coverage map, create one.
349    else {
350
351      highAddress = size - 1;
352
353      aCoverageMap = new CoverageMap( 0, highAddress );
354      if (!aCoverageMap) {
355
356        fprintf(
357          stderr,
358          "ERROR: DesiredSymbols::createCoverageMap - Unable to allocate "
359          "coverage map for %s\n",
360          symbolName.c_str()
361        );
362        exit( -1 );
363      }
364
365      if ( Verbose )
366        fprintf(
367          stderr,
368          "Created unified coverage map for %s (0x%x - 0x%x)\n",
369          symbolName.c_str(), 0, highAddress
370        );
371      itr->second.unifiedCoverageMap = aCoverageMap;
372      itr->second.stats.sizeInBytes = size;
373    }
374  }
375
376  void DesiredSymbols::determineSourceLines(
377    CoverageRanges* const theRanges,
378    ExecutableInfo* const theExecutable
379
380  )
381  {
382    char*                              base;
383    char                               buffer[512];
384    char*                              cStatus;
385    char                               command[512];
386    std::string                        fileName;
387    CoverageRanges::ranges_t::iterator ritr;
388    char                               rpath[PATH_MAX];
389    FILE*                              tmpfile;
390
391    // Open a temporary file for the uncovered ranges.
392    tmpfile = fopen( "ranges1.tmp", "w" );
393    if ( !tmpfile ) {
394      fprintf(
395        stderr,
396        "ERROR: DesiredSymbols::determineSourceLines - "
397        "unable to open %s\n",
398        "ranges1.tmp"
399      );
400      exit(-1);
401    }
402
403    // Write the range addresses to the temporary file.
404    for (ritr =  theRanges->set.begin();
405         ritr != theRanges->set.end();
406         ritr++ ) {
407      fprintf(
408        tmpfile,
409        "0x%08x\n0x%08x\n",
410        ritr->lowAddress - theExecutable->getLoadAddress(),
411        ritr->highAddress - theExecutable->getLoadAddress()
412      );
413    }
414
415    fclose( tmpfile );
416
417    // Invoke addr2line to generate the source lines for each address.
418    if (theExecutable->hasDynamicLibrary())
419      fileName = theExecutable->getLibraryName();
420    else
421      fileName = theExecutable->getFileName();
422
423    sprintf(
424      command,
425      "%s -e %s <%s | dos2unix >%s",
426      TargetInfo->getAddr2line(),
427      fileName.c_str(),
428      "ranges1.tmp",
429      "ranges2.tmp"
430    );
431    if (system( command )) {
432      fprintf(
433        stderr,
434        "ERROR: DesiredSymbols::determineSourceLines - "
435        "command (%s) failed\n",
436        command
437      );
438      exit( -1 );
439    }
440
441    // Open the addr2line output file.
442    tmpfile = fopen( "ranges2.tmp", "r" );
443    if ( !tmpfile ) {
444      fprintf(
445        stderr,
446        "ERROR: DesiredSymbols::determineSourceLines - "
447        "unable to open %s\n",
448        "ranges2.tmp"
449      );
450      exit(-1);
451    }
452
453    // Process the addr2line output.
454    for (ritr =  theRanges->set.begin();
455         ritr != theRanges->set.end();
456         ritr++ ) {
457
458      cStatus = fgets( buffer, 512, tmpfile );
459      if ( cStatus == NULL ) {
460        fprintf(
461          stderr,
462          "ERROR: DesiredSymbols::determineSourceLines - "
463          "Out of sync in addr2line output\n"
464        );
465        exit( -1 );
466      }
467      buffer[ strlen(buffer) - 1] = '\0';
468
469      // Use only the base filename without directory path.
470      realpath( buffer, rpath );
471      base = basename( rpath );
472
473      ritr->lowSourceLine = std::string( base );
474
475      cStatus = fgets( buffer, 512, tmpfile );
476      if ( cStatus == NULL ) {
477        fprintf(
478          stderr,
479          "ERROR: DesiredSymbols::determineSourceLines - "
480          "Out of sync in addr2line output\n"
481        );
482        exit( -1 );
483      }
484      buffer[ strlen(buffer) - 1] = '\0';
485
486      // Use only the base filename without directory path.
487      realpath( buffer, rpath );
488      base = basename( rpath );
489
490      ritr->highSourceLine = std::string( base );
491    }
492
493    fclose( tmpfile );
494    unlink( "ranges1.tmp" );
495    unlink( "ranges2.tmp" );
496  }
497
498  SymbolInformation* DesiredSymbols::find(
499    const std::string& symbolName
500  )
501  {
502    if (set.find( symbolName ) == set.end())
503      return NULL;
504    else
505      return &set[ symbolName ];
506  }
507
508  void DesiredSymbols::findSourceForUncovered( void )
509  {
510    DesiredSymbols::symbolSet_t::iterator ditr;
511    CoverageRanges*                       theBranches;
512    CoverageRanges*                       theRanges;
513
514    // Process uncovered ranges and/or branches for each symbol.
515    for (ditr = SymbolsToAnalyze->set.begin();
516         ditr != SymbolsToAnalyze->set.end();
517         ditr++) {
518
519      // First the unexecuted ranges, ...
520      theRanges = ditr->second.uncoveredRanges;
521      if (theRanges == NULL)
522        continue;
523
524      if (!theRanges->set.empty()) {
525        if (Verbose)
526          fprintf(
527            stderr,
528            "Looking up source lines for uncovered ranges in %s\n",
529            (ditr->first).c_str()
530          );
531        determineSourceLines(
532          theRanges,
533          ditr->second.sourceFile
534        );
535      }
536
537      // then the uncovered branches.
538      theBranches = ditr->second.uncoveredBranches;
539      if (theBranches == NULL)
540        continue;
541
542      if (!theBranches->set.empty()) {
543        if (Verbose)
544          fprintf(
545            stderr,
546            "Looking up source lines for uncovered branches in %s\n",
547            (ditr->first).c_str()
548          );
549        determineSourceLines(
550          theBranches,
551          ditr->second.sourceFile
552        );
553      }
554    }
555  }
556
557  uint32_t DesiredSymbols::getNumberBranchesAlwaysTaken( void ) const {
558    return stats.branchesAlwaysTaken;
559  };
560
561  uint32_t DesiredSymbols::getNumberBranchesFound( void ) const {
562    return (stats.branchesNotExecuted + stats.branchesExecuted);
563  };
564
565  uint32_t DesiredSymbols::getNumberBranchesNeverTaken( void ) const {
566    return stats.branchesNeverTaken;
567  };
568
569  uint32_t DesiredSymbols::getNumberUncoveredRanges( void ) const {
570    return stats.uncoveredRanges;
571  };
572
573  bool DesiredSymbols::isDesired (
574    const std::string& symbolName
575  ) const
576  {
577    if (set.find( symbolName ) == set.end()) {
578      #if 0
579        fprintf( stderr,
580          "Warning: Unable to find symbol %s\n",
581          symbolName.c_str()
582        );
583      #endif
584      return false;
585    }
586    return true;
587  }
588
589  void DesiredSymbols::mergeCoverageMap(
590    const std::string&           symbolName,
591    const CoverageMapBase* const sourceCoverageMap
592  )
593  {
594    uint32_t              dAddress;
595    CoverageMapBase*      destinationCoverageMap;
596    uint32_t              dMapSize;
597    symbolSet_t::iterator itr;
598    uint32_t              sAddress;
599    uint32_t              sBaseAddress;
600    uint32_t              sMapSize;
601
602    // Ensure that the symbol is a desired symbol.
603    itr = set.find( symbolName );
604
605    if (itr == set.end()) {
606
607      fprintf(
608        stderr,
609        "ERROR: DesiredSymbols::mergeCoverageMap - Unable to merge "
610        "coverage map for %s because it is NOT a desired symbol\n",
611        symbolName.c_str()
612      );
613      exit( -1 );
614    }
615
616    // Ensure that the source and destination coverage maps
617    // are the same size.
618    dMapSize = itr->second.stats.sizeInBytes;
619    sBaseAddress = sourceCoverageMap->getLowAddress();
620    sMapSize = sourceCoverageMap->getHighAddress() - sBaseAddress + 1;
621    if (dMapSize != sMapSize) {
622
623      fprintf(
624        stderr,
625        "ERROR: DesiredSymbols::mergeCoverageMap - Unable to merge "
626        "coverage map for %s because the sizes are different\n",
627        symbolName.c_str()
628      );
629      exit( -1 );
630    }
631
632    // Merge the data for each address.
633    destinationCoverageMap = itr->second.unifiedCoverageMap;
634
635    for (dAddress = 0; dAddress < dMapSize; dAddress++) {
636
637      sAddress = dAddress + sBaseAddress;
638
639      // Merge start of instruction indication.
640      if (sourceCoverageMap->isStartOfInstruction( sAddress ))
641        destinationCoverageMap->setIsStartOfInstruction( dAddress );
642
643      // Merge the execution data.
644      if (sourceCoverageMap->wasExecuted( sAddress ))
645        destinationCoverageMap->setWasExecuted( dAddress );
646
647      // Merge the branch data.
648      if (sourceCoverageMap->wasTaken( sAddress ))
649        destinationCoverageMap->setWasTaken( dAddress );
650
651      if (sourceCoverageMap->wasNotTaken( sAddress ))
652        destinationCoverageMap->setWasNotTaken( dAddress );
653    }
654  }
655
656}
Note: See TracBrowser for help on using the repository browser.