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

5
Last change on this file since 61410db was 61410db, checked in by Chris Johns <chrisj@…>, on 11/28/18 at 21:03:29

tester/coverage: Remove warnings in covoar on Windows.

  • Property mode set to 100644
File size: 15.8 KB
RevLine 
[100f517]1/*! @file DesiredSymbols.cc
2 *  @brief DesiredSymbols Implementation
3 *
[f381f26]4 *  This file contains the implementation of the functions
[100f517]5 *  which provide the functionality of the DesiredSymbols.
6 */
7
[f4378ea]8#ifdef __CYGWIN__
9#undef __STRICT_ANSI__
10#endif
11
[100f517]12#include <limits.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <unistd.h>
17
[3e187ba]18#include <iostream>
19
20#include "rld.h"
21#include <rld-config.h>
22#include "rld-symbols.h"
23#include "rld-files.h"
24
[100f517]25#include "DesiredSymbols.h"
26#include "app_common.h"
27#include "CoverageMap.h"
28#include "ObjdumpProcessor.h"
29
30namespace Coverage {
31
32  DesiredSymbols::DesiredSymbols()
33  {
34  }
35
36  DesiredSymbols::~DesiredSymbols()
37  {
38  }
39
[881824f]40  void DesiredSymbols::load(
[3e187ba]41    const std::string& symbolsSet,
42    const std::string& buildTarget,
43    const std::string& buildBSP,
44    bool               verbose
[100f517]45  )
46  {
[3e187ba]47    rld::files::cache cache;
48
49    //
50    // Load the INI file looking for a top level:
51    //
52    //  [symbols-sets]
53    //  sets = A, B, C
54    //
55    // For each set read the libraries from the configuration file and load.
56    //
57    //  [A]
58    //  libraries = @BUILD-PREFIX@/c/@BSP@/A/libA.a
59    //
60    //  [B]
61    //  libraries = @BUILD-PREFIX@/c/@BSP@/B/libB.a
62    //
63    try {
64      cache.open();
65
66      rld::config::config config;
67
68      if (verbose)
69        std::cerr << "Loading symbol sets: " << symbolsSet << std::endl;
70
71      config.load (symbolsSet);
72
73      const rld::config::section& sym_section = config.get_section("symbol-sets");
74
75      rld::strings sets;
76      rld::config::parse_items (sym_section, "sets", sets, true);
77
78      for (const std::string set : sets) {
79        if (verbose)
80          std::cerr << " Symbol set: " << set << std::endl;
81        const rld::config::section& set_section = config.get_section(set);
82        rld::strings libs;
83        rld::config::parse_items (set_section, "libraries", libs, true);
84        for (std::string lib : libs) {
85          lib = rld::find_replace(lib, "@BUILD-TARGET@", buildTarget);
86          lib = rld::find_replace(lib, "@BSP@", buildBSP);
87          if (verbose)
88            std::cerr << " Loading library: " << lib << std::endl;
89          cache.add(lib);
90        }
91      }
[100f517]92
[3e187ba]93      rld::symbols::table symbols;
[100f517]94
[3e187ba]95      cache.load_symbols (symbols, true);
[100f517]96
[3e187ba]97      for (auto& kv : symbols.globals()) {
98        const rld::symbols::symbol& sym = *(kv.second);
[99c90b3]99        if (sym.type() == sym.st_func)
100          set[sym.name()] = *(new SymbolInformation);
[3e187ba]101      }
102      for (auto& kv : symbols.weaks()) {
103        const rld::symbols::symbol& sym = *(kv.second);
[99c90b3]104        if (sym.type() == sym.st_func)
105          set[sym.name()] = *(new SymbolInformation);
[100f517]106      }
[3e187ba]107    } catch (...) {
108      cache.close();
109      throw;
[100f517]110    }
[3e187ba]111
112    cache.close();
[100f517]113  }
114
115  void DesiredSymbols::preprocess( void )
116  {
117
118    // Look at each symbol.
[efbf8f0]119    for (auto& s : SymbolsToAnalyze->set) {
[100f517]120      // If the unified coverage map does not exist, the symbol was
121      // never referenced by any executable.  Just skip it.
[efbf8f0]122      CoverageMapBase* theCoverageMap = s.second.unifiedCoverageMap;
123      if (theCoverageMap)
124      {
125        // Mark any branch and NOP instructions.
126        for (auto& f : s.second.instructions) {
127          if (f.isBranch)
128            theCoverageMap->setIsBranch( f.address - s.second.baseAddress );
129          if (f.isNop)
130            theCoverageMap->setIsNop( f.address - s.second.baseAddress );
[100f517]131        }
132      }
133    }
134  }
135
136  void DesiredSymbols::calculateStatistics( void )
137  {
138    // Look at each symbol.
[efbf8f0]139    for (auto& s : SymbolsToAnalyze->set) {
[100f517]140      // If the unified coverage map does not exist, the symbol was
141      // never referenced by any executable.  Just skip it.
[efbf8f0]142      CoverageMapBase* theCoverageMap = s.second.unifiedCoverageMap;
143      if (theCoverageMap)
144      {
145        // Increment the total sizeInBytes byt the bytes in the symbol
146        stats.sizeInBytes += s.second.stats.sizeInBytes;
147
148        // Now scan through the coverage map of this symbol.
149        uint32_t endAddress = s.second.stats.sizeInBytes - 1;
150
151        for (uint32_t a = 0; a <= endAddress; ++a) {
152          // If we are at the start of instruction increment
153          // instruction type counters as needed.
154          if ( theCoverageMap->isStartOfInstruction( a ) ) {
155
156            stats.sizeInInstructions++;
157            s.second.stats.sizeInInstructions++;
158
159            if (!theCoverageMap->wasExecuted( a ) ) {
160              stats.uncoveredInstructions++;
161              s.second.stats.uncoveredInstructions++;
162
163              if ( theCoverageMap->isBranch( a )) {
164                stats.branchesNotExecuted++;
165                s.second.stats.branchesNotExecuted++;
166              }
167            } else if (theCoverageMap->isBranch( a )) {
168              stats.branchesExecuted++;
169              s.second.stats.branchesExecuted++;
170            }
[100f517]171          }
[f381f26]172
[efbf8f0]173          if (!theCoverageMap->wasExecuted( a )) {
174            stats.uncoveredBytes++;
175            s.second.stats.uncoveredBytes++;
176          }
[100f517]177        }
178      }
179    }
180  }
181
182
183  void DesiredSymbols::computeUncovered( void )
184  {
185    // Look at each symbol.
[efbf8f0]186    for (auto& s : SymbolsToAnalyze->set) {
[100f517]187      // If the unified coverage map does not exist, the symbol was
188      // never referenced by any executable.  Just skip it.
[efbf8f0]189      CoverageMapBase* theCoverageMap = s.second.unifiedCoverageMap;
190      if (theCoverageMap)
191      {
192        // Create containers for the symbol's uncovered ranges and branches.
193        CoverageRanges* theRanges = new CoverageRanges();
194        s.second.uncoveredRanges = theRanges;
195        CoverageRanges* theBranches = new CoverageRanges();
196        s.second.uncoveredBranches = theBranches;
197
198        uint32_t a;
199        uint32_t la;
200        uint32_t ha;
201        uint32_t endAddress;
202        uint32_t count;
203
204        // Mark NOPs as executed
205        endAddress = s.second.stats.sizeInBytes - 1;
206        a = 0;
207        while (a < endAddress) {
208          if (!theCoverageMap->wasExecuted( a )) {
209            a++;
210            continue;
[100f517]211          }
212
213          for (ha=a+1;
[efbf8f0]214               ha <= endAddress && !theCoverageMap->isStartOfInstruction( ha );
[100f517]215               ha++)
216            ;
[efbf8f0]217          if ( ha >= endAddress )
218            break;
219
220          if (theCoverageMap->isNop( ha ))
221            do {
222              theCoverageMap->setWasExecuted( ha );
223              ha++;
224              if ( ha >= endAddress )
225                break;
226            } while ( !theCoverageMap->isStartOfInstruction( ha ) );
227          a = ha;
228        }
229
230        // Now scan through the coverage map of this symbol.
231        endAddress = s.second.stats.sizeInBytes - 1;
232        a = 0;
233        while (a <= endAddress) {
234          // If an address was NOT executed, find consecutive unexecuted
235          // addresses and add them to the uncovered ranges.
236          if (!theCoverageMap->wasExecuted( a )) {
237
238            la = a;
239            count = 1;
240            for (ha = a + 1;
241                 ha <= endAddress && !theCoverageMap->wasExecuted( ha );
242                 ha++)
243            {
244              if ( theCoverageMap->isStartOfInstruction( ha ) )
245                count++;
246            }
247            ha--;
248
249            stats.uncoveredRanges++;
250            s.second.stats.uncoveredRanges++;
251            theRanges->add(
252              s.second.baseAddress + la,
253              s.second.baseAddress + ha,
254              CoverageRanges::UNCOVERED_REASON_NOT_EXECUTED,
255              count
[100f517]256            );
[efbf8f0]257            a = ha + 1;
[100f517]258          }
259
[efbf8f0]260          // If an address is a branch instruction, add any uncovered branches
261          // to the uncoverd branches.
262          else if (theCoverageMap->isBranch( a )) {
263            la = a;
264            for (ha = a + 1;
265               ha <= endAddress && !theCoverageMap->isStartOfInstruction( ha );
266                 ha++)
267              ;
268            ha--;
269
270            if (theCoverageMap->wasAlwaysTaken( la )) {
271              stats.branchesAlwaysTaken++;
272              s.second.stats.branchesAlwaysTaken++;
273              theBranches->add(
274                s.second.baseAddress + la,
275                s.second.baseAddress + ha,
276                CoverageRanges::UNCOVERED_REASON_BRANCH_ALWAYS_TAKEN,
277                1
[100f517]278              );
[efbf8f0]279              if (Verbose)
280                std::cerr << "Branch always taken found in" << s.first
281                          << std::hex
282                          << " (0x" << s.second.baseAddress + la
283                          << " - 0x" << s.second.baseAddress + ha
284                          << ")"
285                          << std::dec
286                          << std::endl;
287            }
288            else if (theCoverageMap->wasNeverTaken( la )) {
289              stats.branchesNeverTaken++;
290              s.second.stats.branchesNeverTaken++;
291              theBranches->add(
292                s.second.baseAddress + la,
293                s.second.baseAddress + ha,
294                CoverageRanges::UNCOVERED_REASON_BRANCH_NEVER_TAKEN,
295                1
296                );
297              if (Verbose)
298                std::cerr << "Branch never taken found in " << s.first
299                          << " (0x" << s.second.baseAddress + la
300                          << " - 0x" << s.second.baseAddress + ha
301                          << ")"
302                          << std::dec
303                          << std::endl;
304            }
305            a = ha + 1;
[100f517]306          }
[efbf8f0]307          else
308            a++;
[100f517]309        }
310      }
311    }
312  }
313
314
315  void DesiredSymbols::createCoverageMap(
[cb018bc]316    const std::string& exefileName,
[100f517]317    const std::string& symbolName,
318    uint32_t           size
319  )
320  {
[efbf8f0]321    CoverageMapBase* aCoverageMap;
322    uint32_t         highAddress;
[100f517]323
324    // Ensure that the symbol is a desired symbol.
[efbf8f0]325    symbolSet_t::iterator itr = set.find( symbolName );
[100f517]326
327    if (itr == set.end()) {
[881824f]328      std::ostringstream what;
329      what << "Unable to create unified coverage map for "
330           << symbolName
331           << " because it is NOT a desired symbol";
332      throw rld::error( what, "DesiredSymbols::createCoverageMap" );
[100f517]333    }
334
335    // If we have already created a coverage map, ...
336    if (itr->second.unifiedCoverageMap) {
337
338      // ensure that the specified size matches the existing size.
339      if (itr->second.stats.sizeInBytes != size) {
340
[cb018bc]341        // Changed ERROR to INFO because size mismatch is not treated as
342        // error anymore.
343        // Set smallest size as size and continue.
344        // Update value for longer byte size.
345        // 2015-07-22
[efbf8f0]346        std::cerr << "INFO: DesiredSymbols::createCoverageMap - Attempt to create "
347                  << "unified coverage maps for "
348                  << symbolName
349                  << " with different sizes ("
[99c90b3]350                  << rld::path::basename(exefileName) << '/' << itr->second.stats.sizeInBytes
351                  << " != "
352                  << rld::path::basename(itr->second.sourceFile->getFileName())
353                  << '/' << size << ')'
[efbf8f0]354                  << std::endl;
[cb018bc]355
[100f517]356        if ( itr->second.stats.sizeInBytes < size )
357          itr->second.stats.sizeInBytes = size;
358        else
359          size = itr->second.stats.sizeInBytes;
360      }
361    }
362
363    // If we don't already have a coverage map, create one.
364    else {
365
366      highAddress = size - 1;
367
[cb018bc]368      aCoverageMap = new CoverageMap( exefileName, 0, highAddress );
[100f517]369
370      if ( Verbose )
371        fprintf(
372          stderr,
373          "Created unified coverage map for %s (0x%x - 0x%x)\n",
374          symbolName.c_str(), 0, highAddress
375        );
376      itr->second.unifiedCoverageMap = aCoverageMap;
377      itr->second.stats.sizeInBytes = size;
378    }
379  }
380
381  void DesiredSymbols::determineSourceLines(
382    CoverageRanges* const theRanges,
383    ExecutableInfo* const theExecutable
384
385  )
386  {
[fb987e8]387    for (auto& r : theRanges->set) {
388      std::string location;
389      theExecutable->getSourceAndLine(r.lowAddress, location);
390      r.lowSourceLine = rld::path::basename (location);
391      theExecutable->getSourceAndLine(r.highAddress, location);
392      r.highSourceLine = rld::path::basename (location);
[100f517]393    }
394  }
395
396  SymbolInformation* DesiredSymbols::find(
397    const std::string& symbolName
398  )
399  {
400    if (set.find( symbolName ) == set.end())
401      return NULL;
402    else
403      return &set[ symbolName ];
404  }
405
406  void DesiredSymbols::findSourceForUncovered( void )
407  {
408    // Process uncovered ranges and/or branches for each symbol.
[efbf8f0]409    for (auto& d : SymbolsToAnalyze->set) {
[100f517]410      // First the unexecuted ranges, ...
[efbf8f0]411      CoverageRanges* theRanges = d.second.uncoveredRanges;
412      if (theRanges != nullptr) {
413        if (!theRanges->set.empty()) {
414          if (Verbose)
415            std::cerr << "Looking up source lines for uncovered ranges in "
416                      << d.first
417                      << std::endl;
[61410db]418          determineSourceLines( theRanges, d.second.sourceFile );
[efbf8f0]419        }
[100f517]420
[efbf8f0]421        // then the uncovered branches.
422        CoverageRanges* theBranches = d.second.uncoveredBranches;
423        if (theBranches != nullptr) {
424          if (!theBranches->set.empty()) {
425            if (Verbose)
426              std::cerr << "Looking up source lines for uncovered branches in "
427                        << d.first
428                        << std::endl;
429            determineSourceLines( theBranches, d.second.sourceFile );
430          }
431        }
[100f517]432      }
433    }
434  }
435
436  uint32_t DesiredSymbols::getNumberBranchesAlwaysTaken( void ) const {
437    return stats.branchesAlwaysTaken;
438  };
439
440  uint32_t DesiredSymbols::getNumberBranchesFound( void ) const {
441    return (stats.branchesNotExecuted + stats.branchesExecuted);
442  };
443
444  uint32_t DesiredSymbols::getNumberBranchesNeverTaken( void ) const {
445    return stats.branchesNeverTaken;
446  };
447
448  uint32_t DesiredSymbols::getNumberUncoveredRanges( void ) const {
449    return stats.uncoveredRanges;
450  };
451
452  bool DesiredSymbols::isDesired (
453    const std::string& symbolName
454  ) const
455  {
[99c90b3]456    return set.find( symbolName ) == set.end() ? false : true;
[100f517]457  }
458
459  void DesiredSymbols::mergeCoverageMap(
460    const std::string&           symbolName,
461    const CoverageMapBase* const sourceCoverageMap
462  )
463  {
464    // Ensure that the symbol is a desired symbol.
[efbf8f0]465    symbolSet_t::iterator itr = set.find( symbolName );
[100f517]466
467    if (itr == set.end()) {
[881824f]468      std::ostringstream what;
469      what << "Unable to merge coverage map for "
470           << symbolName
471           << " because it is NOT a desired symbol";
472      throw rld::error( what, "DesiredSymbols::mergeCoverageMap" );
[100f517]473    }
474
[99c90b3]475    SymbolInformation& sinfo = itr->second;
476
[100f517]477    // Ensure that the source and destination coverage maps
478    // are the same size.
[cb018bc]479    // Changed from ERROR msg to INFO, because size mismatch is not
480    // treated as error anymore. 2015-07-20
[99c90b3]481    uint32_t dMapSize = sinfo.stats.sizeInBytes;
[efbf8f0]482    uint32_t sBaseAddress = sourceCoverageMap->getFirstLowAddress();
483    uint32_t sMapSize = sourceCoverageMap->getSize();
[99c90b3]484    if (dMapSize != 0 && dMapSize != sMapSize) {
[efbf8f0]485      std::cerr << "INFO: DesiredSymbols::mergeCoverageMap - Unable to merge "
486                << "coverage map for " << symbolName
[99c90b3]487                << " because the sizes are different ("
488                << "size: " << dMapSize << ", source: " << sMapSize << ')'
[efbf8f0]489                << std::endl;
[100f517]490      return;
491    }
492
493    // Merge the data for each address.
[99c90b3]494    CoverageMapBase* destinationCoverageMap = sinfo.unifiedCoverageMap;
[100f517]495
[efbf8f0]496    for (uint32_t dAddress = 0; dAddress < dMapSize; dAddress++) {
[100f517]497
[efbf8f0]498      uint32_t sAddress = dAddress + sBaseAddress;
[100f517]499
500      // Merge start of instruction indication.
501      if (sourceCoverageMap->isStartOfInstruction( sAddress ))
502        destinationCoverageMap->setIsStartOfInstruction( dAddress );
503
504      // Merge the execution data.
[efbf8f0]505      uint32_t executionCount = sourceCoverageMap->getWasExecuted( sAddress );
[100f517]506      destinationCoverageMap->sumWasExecuted( dAddress, executionCount );
507
508      // Merge the branch data.
509      executionCount = sourceCoverageMap->getWasTaken( sAddress );
510      destinationCoverageMap->sumWasTaken( dAddress, executionCount );
511
512      executionCount = sourceCoverageMap->getWasNotTaken( sAddress );
513      destinationCoverageMap->sumWasNotTaken( dAddress, executionCount );
514    }
515  }
516}
Note: See TracBrowser for help on using the repository browser.