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 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel