summaryrefslogblamecommitdiffstats
path: root/tester/covoar/ExecutableInfo.cc
blob: fc368cec86f26ba6751dc668bcbe3c6b801f4bf4 (plain) (tree)
1
2
3
4
5
6
7
8
9








                                                              

                









                                        

                                     

                                      
   
                                  
                                   
 






                                                              


                                     
 

                                  
                           
 


                                               

                                         
           






















                                                                           




                                                   

                                                                 

         




                         
     
 


                                                                               

   

                                   


                       

   
                                                 
                                                
 


                                                                



                                                  





                                                               



                                                                      


                                               

                                                                
                                                    
                          
                                                 




                        
                                                              
   
                                    

   
                                                                








                                                       
                                                      
   
                           

   





                                                                 
                                                 



                                          
                                




                                  

                                   
 









                                                                    

                                          
                                                                    




                                             

   












                                          

                                                
                                


                                              


                                                                  








                                                         
/*! @file ExecutableInfo.cc
 *  @brief ExecutableInfo Implementation
 *
 *  This file contains the implementation of the functionality
 *  of the ExecutableInfo class.
 */

#include <stdio.h>

#include <rld.h>

#include "ExecutableInfo.h"
#include "app_common.h"
#include "CoverageMap.h"
#include "DesiredSymbols.h"
#include "SymbolTable.h"

namespace Coverage {

  ExecutableInfo::ExecutableInfo(
    const char* const theExecutableName,
    const char* const theLibraryName,
    bool              verbose
    ) : executable(theExecutableName),
        loadAddress(0)
  {
    if (theLibraryName != nullptr)
      libraryName = theLibraryName;

    if (verbose) {
      std::cerr << "Loading executable " << theExecutableName;
      if (theLibraryName != nullptr)
        std::cerr << " (" << theLibraryName << ')';
      std::cerr << std::endl;
    }

    executable.open();
    executable.begin();
    executable.load_symbols(symbols);

    debug.begin(executable.elf());
    debug.load_debug();
    debug.load_functions();

    try {
      for (auto& cu : debug.get_cus()) {
        for (auto& func : cu.get_functions()) {
          if (!func.has_machine_code()) {
            continue;
          }

          if (!SymbolsToAnalyze->isDesired(func.name())) {
            continue;
          }

          if (func.is_inlined()) {
            if (func.is_external()) {
              // Flag it
              std::cerr << "Function is both external and inlined: "
                        << func.name() << std::endl;
            }

            if (func.has_entry_pc()) {
              continue;
            }

            // If the low PC address is zero, the symbol does not appear in
            // this executable.
            if (func.pc_low() == 0) {
              continue;
            }
          }

          // We can't process a zero size function.
          if (func.pc_high() == 0) {
            continue;
          }

          createCoverageMap (cu.name(), func.name(),
                              func.pc_low(), func.pc_high() - 1);
        }
      }
    } catch (...) {
      debug.end();
      executable.end();
      executable.close();
      throw;
    }

    // Can't cleanup handles until the destructor because the information is
    // referenced elsewhere. NOTE: This could cause problems from too many open
    // file descriptors.
  }

  ExecutableInfo::~ExecutableInfo()
  {
    debug.end();
    executable.end();
    executable.close();
  }

  void ExecutableInfo::dumpCoverageMaps( void ) {
    ExecutableInfo::CoverageMaps::iterator  itr;

    for (auto& cm : coverageMaps) {
      std::cerr << "Coverage Map for " << cm.first << std::endl;
      cm.second->dump();
    }
  }

  void ExecutableInfo::dumpExecutableInfo( void ){
    std::cout << std::endl
              << "== Executable info ==" << std::endl
              << "executable = " << getFileName () << std::endl
              << "library = " << libraryName << std::endl
              << "loadAddress = " << loadAddress << std::endl;
    theSymbolTable.dumpSymbolTable();
  }

  CoverageMapBase* ExecutableInfo::getCoverageMap ( uint32_t address )
  {
    CoverageMapBase*       aCoverageMap = NULL;
    CoverageMaps::iterator it;
    std::string            itsSymbol;

    // Obtain the coverage map containing the specified address.
    itsSymbol = theSymbolTable.getSymbol( address );
    if (itsSymbol != "") {
      aCoverageMap = &findCoverageMap(itsSymbol);
    }

    return aCoverageMap;
  }

  const std::string ExecutableInfo::getFileName ( void ) const
  {
    return executable.name().full();
  }

  const std::string ExecutableInfo::getLibraryName( void ) const
  {
    return libraryName;
  }

  uint32_t ExecutableInfo::getLoadAddress( void ) const
  {
    return loadAddress;
  }

  SymbolTable* ExecutableInfo::getSymbolTable ( void )
  {
    return &theSymbolTable;
  }

  CoverageMapBase& ExecutableInfo::findCoverageMap(
    const std::string& symbolName
  )
  {
    CoverageMaps::iterator cmi = coverageMaps.find( symbolName );
    if ( cmi == coverageMaps.end() )
      throw CoverageMapNotFoundError(symbolName);
    return *(cmi->second);
  }

  void ExecutableInfo::createCoverageMap (
    const std::string& fileName,
    const std::string& symbolName,
    uint32_t           lowAddress,
    uint32_t           highAddress
  )
  {
    CoverageMapBase        *theMap;
    CoverageMaps::iterator  itr;

    if ( lowAddress > highAddress ) {
      std::ostringstream what;
      what << "Low address is greater than high address for symbol "
            << symbolName
            << " (" << lowAddress
            << " and " << highAddress
            << ")";
      throw rld::error( what, "ExecutableInfo::createCoverageMap" );
    }

    itr = coverageMaps.find( symbolName );
    if ( itr == coverageMaps.end() ) {
      theMap = new CoverageMap( fileName, lowAddress, highAddress );
      coverageMaps[ symbolName ] = theMap;
    } else {
      theMap = itr->second;
      theMap->Add( lowAddress, highAddress );
    }
  }

  void ExecutableInfo::getSourceAndLine(
    const unsigned int address,
    std::string&       line
  )
  {
    std::string file;
    int         lno;
    debug.get_source (address, file, lno);
    std::ostringstream ss;
    ss << file << ':' << lno;
    line = ss.str ();
  }

  bool ExecutableInfo::hasDynamicLibrary( void )
  {
    return !libraryName.empty();
  }

  void ExecutableInfo::mergeCoverage( void ) {
    for (auto& cm : coverageMaps) {
      if (SymbolsToAnalyze->isDesired( cm.first ))
        SymbolsToAnalyze->mergeCoverageMap( cm.first, cm.second );
    }
  }

  void ExecutableInfo::setLoadAddress( uint32_t address )
  {
    loadAddress = address;
  }

}