[PATCH 7/9] covoar: Use rld tempfile and add signals to clean up in event of crash.
Cillian O'Donnell
cpodonnell8 at gmail.com
Sat Aug 26 08:15:56 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