Changeset 41284c2 in rtems-testing


Ignore:
Timestamp:
May 18, 2010, 2:21:13 PM (9 years ago)
Author:
Glenn Humphrey <glenn.humphrey@…>
Branches:
4.11, 8895273c193787f84c4585a10f6d6aceb3b25dc4
Children:
8fcc6dc
Parents:
c53ae75
Message:

2010-05-18 Glenn Humphrey

Location:
rtems-coverage
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • rtems-coverage/ChangeLog

    rc53ae75 r41284c2  
     12010-05-18      Glenn Humphrey
     2
     3        * DesiredSymbols.cc, DesiredSymbols.h, ExecutableInfo.cc,
     4        ExecutableInfo.h, ObjdumpProcessor.cc, ObjdumpProcessor.h,
     5        TraceConverter.cc, covoar.cc: Added support for analysis of a dynamic
     6        library. The library load address is currently hard-coded and needs
     7        to be read from a file.
     8
    192010-05-18      Joel Sherrill <joel.sherrilL@OARcorp.com>
    210
  • rtems-coverage/DesiredSymbols.cc

    rc53ae75 r41284c2  
    376376  void DesiredSymbols::determineSourceLines(
    377377    CoverageRanges* const theRanges,
    378     const std::string&    executableFileName
     378    ExecutableInfo* const theExecutable
     379
    379380  )
    380381  {
     
    383384    char*                              cStatus;
    384385    char                               command[512];
     386    std::string                        fileName;
    385387    CoverageRanges::ranges_t::iterator ritr;
    386388    char                               rpath[PATH_MAX];
     
    406408        tmpfile,
    407409        "0x%08x\n0x%08x\n",
    408         ritr->lowAddress,
    409         ritr->highAddress
     410        ritr->lowAddress - theExecutable->getLoadAddress(),
     411        ritr->highAddress - theExecutable->getLoadAddress()
    410412      );
    411413    }
     
    414416
    415417    // 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
    416423    sprintf(
    417424      command,
    418425      "%s -e %s <%s | dos2unix >%s",
    419426      TargetInfo->getAddr2line(),
    420       executableFileName.c_str(),
     427      fileName.c_str(),
    421428      "ranges1.tmp",
    422429      "ranges2.tmp"
  • rtems-coverage/DesiredSymbols.h

    rc53ae75 r41284c2  
    1919#include "CoverageMapBase.h"
    2020#include "CoverageRanges.h"
     21#include "ExecutableInfo.h"
    2122#include "ObjdumpProcessor.h"
    2223
     
    134135
    135136    /*!
    136      *  This member contains the name of the file that was used to
     137     *  This member contains the executable that was used to
    137138     *  generate the disassembled instructions.
    138139     */
    139     std::string sourceFile;
     140    ExecutableInfo* sourceFile;
    140141
    141142    /*!
     
    326327    void determineSourceLines(
    327328      CoverageRanges* const theRanges,
    328       const std::string&    executableFileName
     329      ExecutableInfo* const theExecutable
    329330    );
    330331
  • rtems-coverage/ExecutableInfo.cc

    rc53ae75 r41284c2  
    2020namespace Coverage {
    2121
    22   ExecutableInfo::ExecutableInfo( const char* const executableName )
     22  ExecutableInfo::ExecutableInfo(
     23    const char* const theExecutableName,
     24    const char* const theLibraryName
     25  )
    2326  {
    24     fileName = executableName;
    25     theSymbolTable = NULL;
     27    executableName = theExecutableName;
     28    loadAddress = 0;
     29    libraryName = "";
     30    if (theLibraryName)
     31      libraryName = theLibraryName;
     32    theSymbolTable = new SymbolTable();
    2633  }
    2734
     
    5966  std::string ExecutableInfo::getFileName ( void ) const
    6067  {
    61     return fileName;
     68    return executableName;
    6269  }
     70
     71  std::string ExecutableInfo::getLibraryName( void ) const
     72  {
     73    return libraryName;
     74  }
     75
     76  uint32_t ExecutableInfo::getLoadAddress( void ) const
     77  {
     78    return loadAddress;
     79  }
     80
    6381
    6482  SymbolTable* ExecutableInfo::getSymbolTable ( void ) const
    6583  {
    6684    return theSymbolTable;
    67   }
    68 
    69   void ExecutableInfo::initialize( void )
    70   {
    71     // Create the symbol table.
    72     theSymbolTable = new SymbolTable();
    7385  }
    7486
     
    95107  }
    96108
     109  bool ExecutableInfo::hasDynamicLibrary( void )
     110  {
     111     return (libraryName != "");
     112  }
     113
    97114  void ExecutableInfo::mergeCoverage( void ) {
    98115    ExecutableInfo::coverageMaps_t::iterator  itr;
     
    103120  }
    104121
     122  void ExecutableInfo::setLoadAddress( uint32_t address )
     123  {
     124    loadAddress = address;
     125  }
     126
    105127}
  • rtems-coverage/ExecutableInfo.h

    rc53ae75 r41284c2  
    3333     *  This method constructs an ExecutableInfo instance.
    3434     *
    35      *  @param[in] executableName specifies the filename of the executable
     35     *  @param[in] theExecutableName specifies the name of the executable
     36     *  @param[in] theLibraryName specifies the name of the executable
    3637     */
    37     ExecutableInfo( const char* const executableName );
     38    ExecutableInfo(
     39      const char* const theExecutableName,
     40      const char* const theLibraryName = NULL
     41    );
    3842
    3943    /*!
     
    6670
    6771    /*!
     72     *  This method returns the library name associated with the executable.
     73     *
     74     *  @return Returns the executable's library name
     75     */
     76    std::string getLibraryName( void ) const;
     77
     78    /*!
     79     *  This method returns the load address of the dynamic library
     80     *
     81     *  @return Returns the load address of the dynamic library
     82     */
     83    uint32_t getLoadAddress( void ) const;
     84
     85    /*!
    6886     *  This method returns a pointer to the executable's symbol table.
    6987     *
     
    7189     */
    7290    SymbolTable* getSymbolTable( void ) const;
    73 
    74     /*!
    75      *  This method initializes the ExecutableInfo instance.
    76      */
    77     void initialize( void );
    7891
    7992    /*!
     
    93106
    94107    /*!
     108     *  This method indicates whether a dynamic library has been
     109     *  associated with the executable.
     110     *
     111     *  @return Returns TRUE if
     112     */
     113    bool hasDynamicLibrary( void );
     114
     115    /*!
    95116     *  This method merges the coverage maps for this executable into
    96117     *  the unified coverage map.
    97118     */
    98119    void mergeCoverage( void );
     120
     121    /*!
     122     *  This method sets the load address of the dynamic library
     123     *
     124     *  @param[in] address specifies the load address of the dynamic
     125     *             library
     126     */
     127    void setLoadAddress( uint32_t address );
    99128
    100129  private:
     
    107136
    108137    /*!
    109      *  This member variable contains the filename of the executable.
     138     *  This member variable contains the name of the executable.
    110139     */
    111     std::string fileName;
     140    std::string executableName;
     141
     142    /*!
     143     *  This member variable contains the name of a dynamic library
     144     *  associated with the executable.
     145     */
     146    std::string libraryName;
     147
     148    /*!
     149     *  This member variable contains the load address of a dynamic library
     150     *  if one has been specified for the executable.
     151     */
     152    uint32_t loadAddress;
    112153
    113154    /*!
    114155     *  This member variable contains a pointer to the symbol table
    115      *  of the executable.
     156     *  of the executable or library.
    116157     */
    117158    SymbolTable* theSymbolTable;
  • rtems-coverage/ObjdumpProcessor.cc

    rc53ae75 r41284c2  
    8585    symbolInfo = SymbolsToAnalyze->find( symbolName );
    8686    if (symbolInfo->instructions.empty()) {
    87       symbolInfo->sourceFile = executableInfo->getFileName();
     87      symbolInfo->sourceFile = executableInfo;
    8888      symbolInfo->baseAddress = lowAddress;
    8989      symbolInfo->instructions = instructions;
     
    126126  }
    127127
     128  uint32_t ObjdumpProcessor::determineLoadAddress(
     129    ExecutableInfo* theExecutable
     130  )
     131  {
     132#if 0
     133    char         buffer[ 512 ];
     134    char*        cStatus;
     135    static FILE* gdbCommands = NULL;
     136    int          items;
     137    uint32_t     loadAddress;
     138    FILE*        loadAddressFile = NULL;
     139    FILE*        objdumpFile = NULL;
     140    uint32_t     offset;
     141    int          status;
     142    char         terminator;
     143
     144    // This method should only be call for a dynamic library.
     145    if (!theExecutable->hasDynamicLibrary())
     146      return 0;
     147
     148    //
     149    // Invoke gdb to determine the physical load address
     150    // of the .text section.
     151    //
     152
     153    // Create a gdb input commands file.
     154    if (!gdbCommands) {
     155
     156      gdbCommands = fopen( "gdbCommands", "w" );
     157      if (!gdbCommands) {
     158        fprintf(
     159          stderr,
     160          "ERROR: ObjdumpProcessor::determineLoadAddress - "
     161          "unable to create gdbCommands\n"
     162        );
     163        exit( -1 );
     164      }
     165
     166      fprintf(
     167        gdbCommands,
     168        "set pagination off\n"
     169        "b main\n"
     170        "r\n"
     171        "info sharedlibrary\n"
     172        "quit\n"
     173      );
     174
     175      fclose( gdbCommands );
     176    }
     177
     178    // Invoke gdb.
     179    sprintf(
     180      buffer,
     181      "gdb -x gdbCommands %s | grep %s | cut -d ' ' -f1 > %s",
     182      (theExecutable->getFileName()).c_str(),
     183      (theExecutable->getLibraryName()).c_str(),
     184      "library_addr.tmp"
     185    );
     186
     187    status = system( buffer );
     188    if (status) {
     189      fprintf(
     190        stderr,
     191        "ERROR: ObjdumpProcessor::determineLoadAddress - "
     192        "command (%s) failed with %d\n",
     193        buffer,
     194        status
     195      );
     196      exit( -1 );
     197    }
     198
     199    // Read load address.
     200    loadAddressFile = fopen( "library_addr.tmp", "r" );
     201    if (!loadAddressFile) {
     202      fprintf(
     203        stderr,
     204        "ERROR: ObjdumpProcessor::determineLoadAddress - "
     205        "unable to open library_addr.tmp\n"
     206      );
     207      exit( -1 );
     208    }
     209
     210    cStatus = fgets( buffer, 512, loadAddressFile );
     211    items = sscanf(
     212      buffer, "%x", &loadAddress
     213    );
     214
     215    fclose( loadAddressFile );
     216    unlink( "library_addr.tmp" );
     217
     218    //
     219    // Partially process an objdump of the library to determine the first
     220    // symbol's offset from the physical load address of the library.
     221    //
     222
     223    // Obtain the objdump file.
     224    objdumpFile = getFile( theExecutable->getLibraryName() );
     225
     226    // Process the objdump file.
     227    while ( 1 ) {
     228
     229      // Get a line.
     230      cStatus = fgets( buffer, 512, objdumpFile );
     231      if (cStatus == NULL) {
     232        fprintf(
     233          stderr,
     234          "ERROR: ObjdumpProcessor::determineLoadAddress - "
     235          "no symbol found in objdump file\n"
     236        );
     237        exit( -1 );
     238      }
     239
     240      // Look for the start of a symbol's objdump and extract
     241      // address and symbol (i.e. address <symbolname>:).
     242      items = sscanf(
     243        buffer,
     244        "%x <%*[^>]>%c",
     245        &offset, &terminator
     246      );
     247
     248      // If all items found, we have found the first symbol's objdump.
     249      if ((items == 2) && (terminator == ':')) {
     250        break;
     251      }
     252    }
     253
     254    return (loadAddress - offset);
     255# endif
     256    return 0x42084000;
     257  }
     258
    128259  bool ObjdumpProcessor::IsBranch(
    129260    const char *instruction
     
    131262  {
    132263    if ( !TargetInfo ) {
    133       fprintf( stderr, "ERROR!!! unknown architecture!!!\n");
     264      fprintf(
     265        stderr,
     266        "ERROR: ObjdumpProcessor::IsBranch - unknown architecture\n"
     267      );
    134268      assert(0);
    135269      return false;
     
    144278  {
    145279    if ( !TargetInfo ) {
    146       fprintf( stderr, "ERROR!!! unknown architecture!!!\n");
     280      fprintf(
     281        stderr,
     282        "ERROR: ObjdumpProcessor::isBranchLine - unknown architecture\n"
     283      );
    147284      assert(0);
    148285      return false;
     
    157294  )
    158295  {
    159 
    160296    if ( !TargetInfo ){
    161       fprintf( stderr, "ERROR!!! unknown architecture!!!\n");
    162       fprintf( stderr, "HOW LARGE IS NOP ON THIS ARCHITECTURE? -- fix me\n" );
     297      fprintf(
     298        stderr,
     299        "ERROR: ObjdumpProcessor::isNop - unknown architecture\n"
     300      );
    163301      assert(0);
    164302      return false;
     
    168306  }
    169307
    170   FILE* ObjdumpProcessor::getFile(
    171     std::string exeFileName
    172   )
     308  FILE* ObjdumpProcessor::getFile( std::string fileName )
    173309  {
    174310    char               dumpFile[128];
     
    177313    int                status;
    178314
    179     sprintf(dumpFile,"%s.dmp", exeFileName.c_str() );
     315    sprintf( dumpFile, "%s.dmp", fileName.c_str() );
    180316     
    181317    // Generate the objdump.
    182     if ( FileIsNewer( exeFileName.c_str(), dumpFile )) {
     318    if (FileIsNewer( fileName.c_str(), dumpFile )) {
    183319      sprintf(
    184320        buffer,
    185321        "%s -da --section=.text --source %s | sed -e \'s/ *$//\' >%s",
    186322        TargetInfo->getObjdump(),
    187          exeFileName.c_str(),
     323        fileName.c_str(),
    188324        dumpFile
    189325      );
     
    233369  }
    234370
    235   void ObjdumpProcessor::loadAddressTable (std::string executableFileName )
     371  void ObjdumpProcessor::loadAddressTable (
     372    ExecutableInfo* const executableInformation
     373  )
    236374  {
    237375    char               buffer[ 512 ];
    238376    char*              cStatus;
    239     uint32_t           instructionAddress;
    240377    int                items;
    241378    FILE*              objdumpFile;
     379    uint32_t           offset;
    242380    char               terminator;
    243381
    244     objdumpFile = getFile( executableFileName );
     382    // Obtain the objdump file.
     383    if (!executableInformation->hasDynamicLibrary())
     384      objdumpFile = getFile( executableInformation->getFileName() );
     385    else
     386      objdumpFile = getFile( executableInformation->getLibraryName() );
    245387
    246388    // Process all lines from the objdump file.
     
    258400        buffer,
    259401        "%x%c",
    260         &instructionAddress, &terminator
     402        &offset, &terminator
    261403      );
    262404
    263405      // If it looks like an instruction ...
    264406      if ((items == 2) && (terminator == ':')){
    265         objdumpList.push_back(instructionAddress);
     407        objdumpList.push_back(
     408          executableInformation->getLoadAddress() + offset
     409        );
    266410      }
    267411    }
     
    272416  )
    273417  {
    274     uint32_t           address;
    275     uint32_t           baseAddress = 0;
    276418    char               buffer[ 512 ];
    277419    char*              cStatus;
    278420    std::string        currentSymbol = "";
    279     uint32_t           instructionAddress;
     421    uint32_t           endAddress;
     422    uint32_t           instructionOffset;
    280423    int                items;
    281424    objdumpLine_t      lineInfo;
    282425    FILE*              objdumpFile;
     426    uint32_t           offset;
    283427    bool               processSymbol = false;
     428    uint32_t           startAddress = 0;
    284429    char               symbol[ 100 ];
    285430    char               terminator1;
     
    288433
    289434    // Obtain the objdump file.
    290     objdumpFile = getFile( executableInformation->getFileName() );
     435    if (!executableInformation->hasDynamicLibrary())
     436      objdumpFile = getFile( executableInformation->getFileName() );
     437    else
     438      objdumpFile = getFile( executableInformation->getLibraryName() );
    291439
    292440    // Process all lines from the objdump file.
     
    302450            executableInformation,
    303451            currentSymbol,
    304             baseAddress,
    305             address,  // XXX fix to determine correct end address
     452            startAddress,
     453            executableInformation->getLoadAddress() + offset,
    306454            theInstructions
    307455          );
     
    311459            "         may be incorrect.  It was the last symbol in %s\n"
    312460            "         and the length of its last instruction is assumed "
    313                 "to be one.\n",
     461            "         to be one.\n",
    314462            currentSymbol.c_str(),
    315463            executableInformation->getFileName().c_str()
     
    329477
    330478      // Look for the start of a symbol's objdump and extract
    331       // address and symbol (i.e. address <symbolname>:).
     479      // offset and symbol (i.e. offset <symbolname>:).
    332480      items = sscanf(
    333481        buffer,
    334482        "%x <%[^>]>%c",
    335         &address, symbol, &terminator1
     483        &offset, symbol, &terminator1
    336484      );
    337485
    338486      // If all items found, we are at the beginning of a symbol's objdump.
    339487      if ((items == 3) && (terminator1 == ':')) {
     488
     489        endAddress = executableInformation->getLoadAddress() + offset - 1;
    340490
    341491        // If we are currently processing a symbol, finalize it.
     
    344494            executableInformation,
    345495            currentSymbol,
    346             baseAddress,
    347             address - 1,
     496            startAddress,
     497            endAddress,
    348498            theInstructions
    349499          );
     
    351501
    352502        // Start processing of a new symbol.
    353         baseAddress = 0;
     503        startAddress = 0;
    354504        currentSymbol = "";
    355505        processSymbol = false;
     
    358508        // See if the new symbol is one that we care about.
    359509        if (SymbolsToAnalyze->isDesired( symbol )) {
    360           baseAddress = address;
     510          startAddress = executableInformation->getLoadAddress() + offset;
    361511          currentSymbol = symbol;
    362512          processSymbol = true;
     
    371521          buffer,
    372522          "%x%c\t%*[^\t]%c",
    373           &instructionAddress, &terminator1, &terminator2
     523          &instructionOffset, &terminator1, &terminator2
    374524        );
    375525
     
    378528
    379529          // update the line's information, save it and ...
    380           lineInfo.address       = instructionAddress;
     530          lineInfo.address =
     531           executableInformation->getLoadAddress() + instructionOffset;
    381532          lineInfo.isInstruction = true;
    382533          lineInfo.isNop         = isNop( buffer, lineInfo.nopSize );
  • rtems-coverage/ObjdumpProcessor.h

    rc53ae75 r41284c2  
    8787    virtual ~ObjdumpProcessor();
    8888
     89    uint32_t determineLoadAddress(
     90      ExecutableInfo* theExecutable
     91    );
     92
    8993    /*!
    9094     *  This method returns a file pointer to the objdump file
    91      *  for the given executable file name. 
     95     *  for the given file name. 
    9296     */
    93     FILE* getFile(
    94       std::string exeFileName
    95     );
     97    FILE* getFile( std::string fileName );
    9698
    9799    /*!
     
    100102     */
    101103    void loadAddressTable (
    102       std::string executableFileName
     104      ExecutableInfo* const executableInformation
    103105    );
    104106
  • rtems-coverage/TraceConverter.cc

    rc53ae75 r41284c2  
    2424#include "TargetFactory.h"
    2525
    26 char *progname;
     26//const char* dynamicLibrary = "libfuncs.so";
     27const char* dynamicLibrary = NULL;
     28char*       progname;
    2729
    2830void usage()
     
    4850  const char                  *tracefile  =  "";
    4951  const char                  *logname = "/tmp/qemu.log";
     52  Coverage::ExecutableInfo*    executableInfo;
    5053   
    5154  //
     
    8487  TargetInfo = Target::TargetFactory( cpuname );
    8588
     89  if (dynamicLibrary)
     90    executableInfo = new Coverage::ExecutableInfo(
     91      executable, dynamicLibrary
     92    );
     93  else
     94    executableInfo = new Coverage::ExecutableInfo( executable );
     95
    8696  objdumpProcessor = new Coverage::ObjdumpProcessor();
    8797 
    88   objdumpProcessor->loadAddressTable( executable );
     98  // If a dynamic library was specified, determine the load address.
     99  if (dynamicLibrary)
     100    executableInfo->setLoadAddress(
     101      objdumpProcessor->determineLoadAddress( executableInfo )
     102    );
     103
     104  objdumpProcessor->loadAddressTable( executableInfo );
    89105
    90106  log.processFile( logname );
  • rtems-coverage/covoar.cc

    rc53ae75 r41284c2  
    3535Coverage::CoverageFormats_t          coverageFormat;
    3636Coverage::CoverageReaderBase*        coverageReader = NULL;
     37const char*                          dynamicLibrary = NULL;
    3738char*                                executable = NULL;
    3839char*                                executableExtension = NULL;
     
    154155  progname = argv[0];
    155156
    156   while ((opt = getopt(argc, argv, "C:1:e:c:E:f:s:T:O:v")) != -1) {
     157  while ((opt = getopt(argc, argv, "C:1:L:e:c:E:f:s:T:O:v")) != -1) {
    157158    switch (opt) {
    158159      case 'C': CoverageConfiguration->processFile( optarg ); break;
    159160      case '1': singleExecutable      = optarg; break;
     161      case 'L': dynamicLibrary        = optarg; break;
    160162      case 'e': executableExtension   = optarg; break;
    161163      case 'c': coverageFileExtension = optarg; break;
     
    210212      // executable information.
    211213      if (!coverageFileNames.empty()) {
    212         executableInfo = new Coverage::ExecutableInfo( singleExecutable );
     214        if (dynamicLibrary)
     215          executableInfo = new Coverage::ExecutableInfo(
     216            singleExecutable, dynamicLibrary
     217          );
     218        else
     219          executableInfo = new Coverage::ExecutableInfo( singleExecutable );
     220
    213221        executablesToAnalyze.push_back( executableInfo );
    214222      }
     
    352360  objdumpProcessor = new Coverage::ObjdumpProcessor();
    353361
    354   // Process each executable to analyze.
     362  // Prepare each executable for analysis.
    355363  for (eitr = executablesToAnalyze.begin();
    356364       eitr != executablesToAnalyze.end();
     
    364372      );
    365373
    366     // Create the executable information.
    367     (*eitr)->initialize();
     374    // If a dynamic library was specified, determine the load address.
     375    if (dynamicLibrary)
     376      (*eitr)->setLoadAddress(
     377        objdumpProcessor->determineLoadAddress( *eitr )
     378      );
    368379
    369380    // Load the objdump for the symbols in this executable.
Note: See TracChangeset for help on using the changeset viewer.