summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCillian O'Donnell <cpodonnell8@gmail.com>2017-08-26 09:15:56 +0100
committerChris Johns <chrisj@rtems.org>2017-08-29 18:06:11 +1000
commit6a4859e627fa10690741d36b2f1c39a1c4d6cc3a (patch)
tree39e04c8186bd342f815cfe79641a16febb6c3bc2
parentcovoar/wscript: Add paths to rtemstoolkit to build. (diff)
downloadrtems-tools-6a4859e627fa10690741d36b2f1c39a1c4d6cc3a.tar.bz2
covoar: Use rld tempfile and add signals to clean up in event of crash.
Use rld tempfile for temporary files and add fatal signal handling to clean them up in the event of a crash.
-rw-r--r--tester/covoar/ObjdumpProcessor.cc168
-rw-r--r--tester/covoar/ObjdumpProcessor.h30
-rw-r--r--tester/covoar/TraceConverter.cc60
-rw-r--r--tester/covoar/TraceReaderLogQEMU.cc9
-rw-r--r--tester/covoar/TraceReaderLogQEMU.h2
-rw-r--r--tester/covoar/TraceWriterQEMU.cc10
-rw-r--r--tester/covoar/TraceWriterQEMU.h2
-rw-r--r--tester/covoar/covoar.cc55
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;
}