[PATCH 7/9] covoar: Use rld tempfile and add signals to clean up in event of crash.

Cillian O'Donnell cpodonnell8 at gmail.com
Fri Aug 25 21:53:30 UTC 2017


Use rld tempfile for temporary files and add fatal signal handling to clean
them up in the event of a crash.
---
 tester/covoar/ObjdumpProcessor.cc   | 168 +++++++++++++++++-------------------
 tester/covoar/ObjdumpProcessor.h    |  30 ++++---
 tester/covoar/TraceConverter.cc     |  60 ++++++++++---
 tester/covoar/TraceReaderLogQEMU.cc |   9 +-
 tester/covoar/TraceReaderLogQEMU.h  |   2 +
 tester/covoar/TraceWriterQEMU.cc    |  10 +--
 tester/covoar/TraceWriterQEMU.h     |   2 +
 tester/covoar/covoar.cc             |  55 +++++++++++-
 8 files changed, 206 insertions(+), 130 deletions(-)

diff --git a/tester/covoar/ObjdumpProcessor.cc b/tester/covoar/ObjdumpProcessor.cc
index 01692b8..b916984 100644
--- a/tester/covoar/ObjdumpProcessor.cc
+++ b/tester/covoar/ObjdumpProcessor.cc
@@ -21,6 +21,9 @@
 #include "SymbolTable.h"
 #include "TargetFactory.h"
 
+#include "rld.h"
+#include "rld-process.h"
+
 namespace Coverage {
 
   void finalizeSymbol(
@@ -231,49 +234,33 @@ namespace Coverage {
     return TargetInfo->isNopLine( line, size );
   }
 
-  FILE* ObjdumpProcessor::getFile( std::string fileName )
+  void ObjdumpProcessor::getFile(
+    std::string fileName,
+    rld::process::tempfile& objdumpFile,
+    rld::process::tempfile& err
+    )
   {
-    char               dumpFile[128];
-    FILE*              objdumpFile;
-    char               buffer[ 512 ];
-    int                status;
-
-    sprintf( dumpFile, "%s.dmp", fileName.c_str() );
-
-    // Generate the objdump.
-    if (FileIsNewer( fileName.c_str(), dumpFile )) {
-      sprintf(
-        buffer,
-        "%s -Cda --section=.text --source %s | sed -e \'s/ *$//\' >%s",
-        TargetInfo->getObjdump(),
-        fileName.c_str(),
-        dumpFile
-      );
-
-      status = system( buffer );
-      if (status) {
-        fprintf(
-          stderr,
-          "ERROR: ObjdumpProcessor::getFile - command (%s) failed with %d\n",
-          buffer,
-          status
-        );
-        exit( -1 );
+    rld::process::status        status;
+    rld::process::arg_container args = { TargetInfo->getObjdump(),
+                                         "-Cda", "--section=.text", "--source",
+                                         fileName };
+    try
+    {
+      status = rld::process::execute( TargetInfo->getObjdump(),
+               args, objdumpFile.name(), err.name() );
+      if ( (status.type != rld::process::status::normal)
+           || (status.code != 0) ) {
+        throw rld::error( "Objdump error", "generating objdump" );
+      }
+    } catch( rld::error& err )
+      {
+        std::cout << "Error while running" << TargetInfo->getObjdump()
+                  << "for" << fileName << std::endl;
+        std::cout << err.what << " in " << err.where << std::endl;
+        return;
       }
-    }
-
-    // Open the objdump file.
-    objdumpFile = fopen( dumpFile, "r" );
-    if (!objdumpFile) {
-      fprintf(
-        stderr,
-        "ERROR: ObjdumpProcessor::getFile - unable to open %s\n",
-        dumpFile
-      );
-      exit(-1);
-    }
 
-    return objdumpFile;
+    objdumpFile.open( true );
   }
 
   uint32_t ObjdumpProcessor::getAddressAfter( uint32_t address )
@@ -295,40 +282,40 @@ namespace Coverage {
   }
 
   void ObjdumpProcessor::loadAddressTable (
-    ExecutableInfo* const executableInformation
+    ExecutableInfo* const    executableInformation,
+    rld::process::tempfile&  objdumpFile,
+    rld::process::tempfile&  err
   )
   {
-    char*              cStatus;
-    int                items;
-    FILE*              objdumpFile;
-    uint32_t           offset;
-    char               terminator;
+    int          items;
+    uint32_t     offset;
+    char         terminator;
+    std::string  line;
 
     // Obtain the objdump file.
-    if (!executableInformation->hasDynamicLibrary())
-      objdumpFile = getFile( executableInformation->getFileName() );
+    if ( !executableInformation->hasDynamicLibrary() )
+      getFile( executableInformation->getFileName(), objdumpFile, err );
     else
-      objdumpFile = getFile( executableInformation->getLibraryName() );
+      getFile( executableInformation->getLibraryName(), objdumpFile, err );
 
     // Process all lines from the objdump file.
-    while ( 1 ) {
+    while ( true ) {
 
       // Get the line.
-      cStatus = fgets( inputBuffer, MAX_LINE_LENGTH, objdumpFile );
-      if (cStatus == NULL) {
+      objdumpFile.read_line( line );
+      if ( line.empty() ) {
         break;
       }
-      inputBuffer[ strlen(inputBuffer) - 1] = '\0';
 
       // See if it is the dump of an instruction.
       items = sscanf(
-        inputBuffer,
+        line.c_str(),
         "%x%c",
         &offset, &terminator
       );
 
       // If it looks like an instruction ...
-      if ((items == 2) && (terminator == ':')){
+      if ((items == 2) && (terminator == ':')) {
         objdumpList.push_back(
           executableInformation->getLoadAddress() + offset
         );
@@ -337,42 +324,42 @@ namespace Coverage {
   }
 
   void ObjdumpProcessor::load(
-    ExecutableInfo* const executableInformation
+    ExecutableInfo* const    executableInformation,
+    rld::process::tempfile&  objdumpFile,
+    rld::process::tempfile&  err
   )
   {
-    char*              cStatus;
-    std::string        currentSymbol = "";
-    uint32_t           endAddress;
-    uint32_t           instructionOffset;
-    int                items;
-    int                found;
-    objdumpLine_t      lineInfo;
-    FILE*              objdumpFile;
-    uint32_t           offset;
-    bool               processSymbol = false;
-    uint32_t           startAddress = 0;
-    char               symbol[ MAX_LINE_LENGTH ];
-    char               terminator1;
-    char               terminatorOne;
-    char               terminator2;
-    objdumpLines_t     theInstructions;
-    char               instruction[ MAX_LINE_LENGTH ];
-    char               ID[ MAX_LINE_LENGTH ];
-    std::string        call = "";
-    std::string        jumpTableID = "";
+    std::string     currentSymbol = "";
+    uint32_t        endAddress;
+    uint32_t        instructionOffset;
+    int             items;
+    int             found;
+    objdumpLine_t   lineInfo;
+    uint32_t        offset;
+    bool            processSymbol = false;
+    uint32_t        startAddress = 0;
+    char            symbol[ MAX_LINE_LENGTH ];
+    char            terminator1;
+    char            terminatorOne;
+    char            terminator2;
+    objdumpLines_t  theInstructions;
+    char            instruction[ MAX_LINE_LENGTH ];
+    char            ID[ MAX_LINE_LENGTH ];
+    std::string     call = "";
+    std::string     jumpTableID = "";
+    std::string     line = "";
 
     // Obtain the objdump file.
-    if (!executableInformation->hasDynamicLibrary())
-      objdumpFile = getFile( executableInformation->getFileName() );
+    if ( !executableInformation->hasDynamicLibrary() )
+      getFile( executableInformation->getFileName(), objdumpFile, err );
     else
-      objdumpFile = getFile( executableInformation->getLibraryName() );
+      getFile( executableInformation->getLibraryName(), objdumpFile, err );
 
-    // Process all lines from the objdump file.
-    while ( 1 ) {
+    while ( true ) {
 
       // Get the line.
-      cStatus = fgets( inputBuffer, MAX_LINE_LENGTH, objdumpFile );
-      if (cStatus == NULL) {
+      objdumpFile.read_line( line );
+      if ( line.empty() ) {
 
         // If we are currently processing a symbol, finalize it.
         if (processSymbol) {
@@ -393,12 +380,11 @@ namespace Coverage {
             executableInformation->getFileName().c_str()
           );
         }
+        objdumpFile.close();
         break;
       }
 
-      inputBuffer[ strlen(inputBuffer) - 1] = '\0';
-
-      lineInfo.line          = inputBuffer;
+      lineInfo.line          = line;
       lineInfo.address       = 0xffffffff;
       lineInfo.isInstruction = false;
       lineInfo.isNop         = false;
@@ -408,14 +394,14 @@ namespace Coverage {
       // Look for the start of a symbol's objdump and extract
       // offset and symbol (i.e. offset <symbolname>:).
       items = sscanf(
-        inputBuffer,
+        line.c_str(),
         "%x <%[^>]>%c",
         &offset, symbol, &terminator1
       );
 
       // See if it is a jump table.
       found = sscanf(
-        inputBuffer,
+        line.c_str(),
         "%x%c\t%*[^\t]%c%s %*x %*[^+]%s",
         &instructionOffset, &terminatorOne, &terminator2, instruction, ID
       );
@@ -477,7 +463,7 @@ namespace Coverage {
 
         // See if it is the dump of an instruction.
         items = sscanf(
-          inputBuffer,
+          line.c_str(),
           "%x%c\t%*[^\t]%c",
           &instructionOffset, &terminator1, &terminator2
         );
@@ -489,8 +475,8 @@ namespace Coverage {
           lineInfo.address =
            executableInformation->getLoadAddress() + instructionOffset;
           lineInfo.isInstruction = true;
-          lineInfo.isNop         = isNop( inputBuffer, lineInfo.nopSize );
-          lineInfo.isBranch      = isBranchLine( inputBuffer );
+          lineInfo.isNop         = isNop( line.c_str(), lineInfo.nopSize );
+          lineInfo.isBranch      = isBranchLine( line.c_str() );
         }
 
         // Always save the line.
diff --git a/tester/covoar/ObjdumpProcessor.h b/tester/covoar/ObjdumpProcessor.h
index 283ac73..c75755d 100644
--- a/tester/covoar/ObjdumpProcessor.h
+++ b/tester/covoar/ObjdumpProcessor.h
@@ -13,6 +13,8 @@
 #include "ExecutableInfo.h"
 #include "TargetBase.h"
 
+#include "rld-process.h"
+
 namespace Coverage {
 
   /*! @class ObjdumpProcessor
@@ -74,11 +76,11 @@ namespace Coverage {
      */
     typedef std::list<objdumpLine_t> objdumpLines_t;
 
-   
+
     /*!
      *  This object defines a list of instruction addresses
      *  that will be extracted from the objdump file.
-     */ 
+     */
     typedef std::list<uint32_t> objdumpFile_t;
 
     /*!
@@ -96,17 +98,21 @@ namespace Coverage {
     );
 
     /*!
-     *  This method returns a file pointer to the objdump file
-     *  for the given file name.  
+     *  This method fills a tempfile with the .text section of objdump
+     *  for the given file name.
      */
-    FILE* getFile( std::string fileName ); 
+    void getFile( std::string fileName,
+                  rld::process::tempfile& dmp,
+                  rld::process::tempfile& err );
 
     /*!
-     *  This method fills the objdumpList list with all the 
+     *  This method fills the objdumpList list with all the
      *  instruction addresses in the object dump file.
      */
     void loadAddressTable (
-      ExecutableInfo* const executableInformation
+      ExecutableInfo* const executableInformation,
+      rld::process::tempfile& dmp,
+      rld::process::tempfile& err
     );
 
     /*!
@@ -114,23 +120,25 @@ namespace Coverage {
      *  the specified executable.
      */
     void load(
-      ExecutableInfo* const executableInformation
+      ExecutableInfo* const executableInformation,
+      rld::process::tempfile& dmp,
+      rld::process::tempfile& err
     );
 
     /*!
-     *  This method returns the next address in othe objdumpList.
+     *  This method returns the next address in the objdumpList.
      */
     uint32_t getAddressAfter( uint32_t address );
 
     /*!
-     *  This method returns true if the instrucation is
+     *  This method returns true if the instruction is
      *  an instruction that results in a code branch, otherwise
      *  it returns false.
      */
     bool IsBranch( const char *instruction );
 
     /*!
-     *  This method returns true if the instruction from 
+     *  This method returns true if the instruction from
      *  the given line in the objdmp file is a branch instruction,
      *  otherwise it returns false.
      */
diff --git a/tester/covoar/TraceConverter.cc b/tester/covoar/TraceConverter.cc
index 0f7a44e..22b0f81 100644
--- a/tester/covoar/TraceConverter.cc
+++ b/tester/covoar/TraceConverter.cc
@@ -10,9 +10,10 @@
 #include <sys/stat.h>
 #include <string.h>
 #include <getopt.h>
+#include <signal.h>
+#include <unistd.h>
 
 #include "qemu-log.h"
-
 #include "TraceReaderLogQEMU.h"
 #include "TraceWriterQEMU.h"
 #include "TraceList.h"
@@ -20,6 +21,9 @@
 #include "app_common.h"
 #include "TargetFactory.h"
 
+#include "rld.h"
+#include "rld-process.h"
+
 char*       progname;
 
 void usage()
@@ -32,6 +36,40 @@ void usage()
   exit(1);
 }
 
+static void
+fatal_signal( int signum )
+{
+  signal( signum, SIG_DFL );
+
+  rld::process::temporaries_clean_up();
+
+  /*
+   * Get the same signal again, this time not handled, so its normal effect
+   * occurs.
+   */
+  kill( getpid(), signum );
+}
+
+static void
+setup_signals( void )
+{
+  if ( signal (SIGINT, SIG_IGN) != SIG_IGN )
+    signal( SIGINT, fatal_signal );
+#ifdef SIGHUP
+  if ( signal( SIGHUP, SIG_IGN ) != SIG_IGN )
+    signal( SIGHUP, fatal_signal );
+#endif
+  if ( signal( SIGTERM, SIG_IGN ) != SIG_IGN )
+    signal( SIGTERM, fatal_signal );
+#ifdef SIGPIPE
+  if ( signal( SIGPIPE, SIG_IGN ) != SIG_IGN )
+    signal( SIGPIPE, fatal_signal );
+#endif
+#ifdef SIGCHLD
+  signal( SIGCHLD, SIG_DFL );
+#endif
+}
+
 int main(
   int    argc,
   char** argv
@@ -45,10 +83,14 @@ int main(
   const char                  *tracefile  =  "";
   const char                  *logname = "/tmp/qemu.log";
   Coverage::ExecutableInfo*    executableInfo;
-   
-  //
-  // Process command line options.
-  //
+  rld::process::tempfile       objdumpFile( ".dmp" );
+  rld::process::tempfile       err( ".err" );
+
+  setup_signals();
+
+   //
+   // Process command line options.
+   //
   progname = argv[0];
 
   while ((opt = getopt(argc, argv, "c:e:l:L:t:v")) != -1) {
@@ -88,17 +130,13 @@ int main(
     executableInfo = new Coverage::ExecutableInfo( executable );
 
   objdumpProcessor = new Coverage::ObjdumpProcessor();
- 
+
   // If a dynamic library was specified, determine the load address.
   if (dynamicLibrary)
     executableInfo->setLoadAddress(
       objdumpProcessor->determineLoadAddress( executableInfo )
     );
-
-  objdumpProcessor->loadAddressTable( executableInfo );
-
+  objdumpProcessor->loadAddressTable( executableInfo, objdumpFile, err );
   log.processFile( logname );
-
   trace.writeFile( tracefile, &log );
-
 }
diff --git a/tester/covoar/TraceReaderLogQEMU.cc b/tester/covoar/TraceReaderLogQEMU.cc
index 2250d2b..508074a 100644
--- a/tester/covoar/TraceReaderLogQEMU.cc
+++ b/tester/covoar/TraceReaderLogQEMU.cc
@@ -35,25 +35,20 @@
  *  reading the QEMU coverage data files.
  */
 
-#include "covoar-config.h"
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <string.h>
 
 #include "qemu-log.h"
-
 #include "app_common.h"
 #include "TraceReaderBase.h"
 #include "TraceReaderLogQEMU.h"
 #include "TraceList.h"
-
-/* XXX really not always right */
-typedef uint32_t target_ulong;
-
 #include "qemu-traces.h"
 
+#include "rld-process.h"
+
 #if HAVE_STAT64
 #define STAT stat64
 #else
diff --git a/tester/covoar/TraceReaderLogQEMU.h b/tester/covoar/TraceReaderLogQEMU.h
index c4877fd..e7b03f0 100644
--- a/tester/covoar/TraceReaderLogQEMU.h
+++ b/tester/covoar/TraceReaderLogQEMU.h
@@ -9,6 +9,8 @@
 
 #include "TraceReaderBase.h"
 
+#include "rld-process.h"
+
 namespace Trace {
 
   /*! @class TraceReaderLogQEMU
diff --git a/tester/covoar/TraceWriterQEMU.cc b/tester/covoar/TraceWriterQEMU.cc
index 29ad2b9..9a8affc 100644
--- a/tester/covoar/TraceWriterQEMU.cc
+++ b/tester/covoar/TraceWriterQEMU.cc
@@ -34,8 +34,6 @@
  *  reading the QEMU coverage data files.
  */
 
-#include "covoar-config.h"
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h>
@@ -44,12 +42,10 @@
 #include "TraceWriterQEMU.h"
 #include "ExecutableInfo.h"
 #include "CoverageMap.h"
-
-/* XXX really not always right */
-typedef uint32_t target_ulong;
-
 #include "qemu-traces.h"
 
+#include "rld-process.h"
+
 #if HAVE_STAT64
 #define STAT stat64
 #else
@@ -167,7 +163,7 @@ namespace Trace {
 
       status = fwrite( &entry, sizeof(entry), 1, traceFile );
       if (status != 1) {
-        fprintf( stderr, "Unable to emtry to %s\n", file );
+        fprintf( stderr, "Unable to write entry to %s\n", file );
         return false;
       }
     }
diff --git a/tester/covoar/TraceWriterQEMU.h b/tester/covoar/TraceWriterQEMU.h
index 3b1c254..254c292 100644
--- a/tester/covoar/TraceWriterQEMU.h
+++ b/tester/covoar/TraceWriterQEMU.h
@@ -11,6 +11,8 @@
 #include "TraceReaderBase.h"
 #include "TraceWriterBase.h"
 
+#include "rld-process.h"
+
 namespace Trace {
 
   /*! @class TraceWriterQEMU
diff --git a/tester/covoar/covoar.cc b/tester/covoar/covoar.cc
index a3f137e..005cb8e 100644
--- a/tester/covoar/covoar.cc
+++ b/tester/covoar/covoar.cc
@@ -23,6 +23,8 @@
 #include "TargetFactory.h"
 #include "GcovData.h"
 
+#include "rld-process.h"
+
 /*
  *  Variables to control general behavior
  */
@@ -45,7 +47,7 @@ char				     gcovBashCommand[256];
 const char*                          target = NULL;
 const char*                          format = NULL;
 FILE*				     gcnosFile = NULL;
-Gcov::GcovData* 		     gcovFile;
+Gcov::GcovData*          gcovFile;
 
 /*
  *  Print program usage message
@@ -146,6 +148,40 @@ void check_configuration(void)
     coverageFormat = Coverage::CoverageFormatToEnum( format );
 }
 
+static void
+fatal_signal( int signum )
+{
+  signal( signum, SIG_DFL );
+
+  rld::process::temporaries_clean_up();
+
+  /*
+   * Get the same signal again, this time not handled, so its normal effect
+   * occurs.
+   */
+  kill( getpid(), signum );
+}
+
+static void
+setup_signals( void )
+{
+  if ( signal( SIGINT, SIG_IGN ) != SIG_IGN )
+    signal( SIGINT, fatal_signal );
+#ifdef SIGHUP
+  if ( signal( SIGHUP, SIG_IGN ) != SIG_IGN )
+    signal( SIGHUP, fatal_signal );
+#endif
+  if ( signal( SIGTERM, SIG_IGN ) != SIG_IGN )
+    signal( SIGTERM, fatal_signal );
+#ifdef SIGPIPE
+  if ( signal( SIGPIPE, SIG_IGN ) != SIG_IGN )
+    signal( SIGPIPE, fatal_signal );
+#endif
+#ifdef SIGCHLD
+  signal( SIGCHLD, SIG_DFL );
+#endif
+}
+
 int main(
   int    argc,
   char** argv
@@ -158,6 +194,11 @@ int main(
   int                                            i;
   int                                            opt;
   const char*                                    singleExecutable = NULL;
+  rld::process::tempfile                         objdumpFile( ".dmp" );
+  rld::process::tempfile                         err( ".err" );
+  bool                                           debug = false;
+
+  setup_signals();
 
   CoverageConfiguration = new Configuration::FileReader(Options);
 
@@ -166,7 +207,7 @@ int main(
   //
   progname = argv[0];
 
-  while ((opt = getopt(argc, argv, "C:1:L:e:c:g:E:f:s:T:O:p:v")) != -1) {
+  while ((opt = getopt(argc, argv, "C:1:L:e:c:g:E:f:s:T:O:p:v:d")) != -1) {
     switch (opt) {
       case 'C': CoverageConfiguration->processFile( optarg ); break;
       case '1': singleExecutable      = optarg; break;
@@ -181,6 +222,7 @@ int main(
       case 'O': outputDirectory       = optarg; break;
       case 'v': Verbose               = true;   break;
       case 'p': projectName           = optarg; break;
+      case 'd': debug                 = true;   break;
       default: /* '?' */
         usage();
         exit( -1 );
@@ -394,7 +436,7 @@ int main(
       );
 
     // Load the objdump for the symbols in this executable.
-    objdumpProcessor->load( *eitr );
+    objdumpProcessor->load( *eitr, objdumpFile, err );
   }
 
   //
@@ -503,5 +545,12 @@ int main(
     AllExplanations->writeNotFound( notFound.c_str() );
   }
 
+  //Leave tempfiles around if debug flag (-d) is enabled.
+  if ( debug ) {
+	objdumpFile.override( "objdump_file" );
+	objdumpFile.keep();
+	err.override( "objdump_exec_log" );
+	err.keep();
+  }
   return 0;
 }
-- 
2.7.4




More information about the devel mailing list