diff options
Diffstat (limited to 'tester/covoar/TraceReaderLogQEMU.cc')
-rw-r--r-- | tester/covoar/TraceReaderLogQEMU.cc | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/tester/covoar/TraceReaderLogQEMU.cc b/tester/covoar/TraceReaderLogQEMU.cc new file mode 100644 index 0000000..2250d2b --- /dev/null +++ b/tester/covoar/TraceReaderLogQEMU.cc @@ -0,0 +1,206 @@ +/* + * RTEMS Tools Project (http://www.rtems.org/) + * Copyright 2014 OAR Corporation + * All rights reserved. + * + * This file is part of the RTEMS Tools package in 'rtems-tools'. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*! @file TraceReaderLogQEMU.cc + * @brief TraceReaderLogQEMU Implementation + * + * This file contains the implementation of the functions supporting + * 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" + +#if HAVE_STAT64 +#define STAT stat64 +#else +#define STAT stat +#endif + +#if HAVE_OPEN64 +#define OPEN fopen64 +#else +#define OPEN fopen +#endif + +namespace Trace { + + TraceReaderLogQEMU::TraceReaderLogQEMU() + { + } + + TraceReaderLogQEMU::~TraceReaderLogQEMU() + { + } + + bool TraceReaderLogQEMU::processFile( + const char* const file + ) + { + bool done = false; + QEMU_LOG_IN_Block_t first = { 0, "", "" }; + QEMU_LOG_IN_Block_t last = { 0, "", "" }; + QEMU_LOG_IN_Block_t nextExecuted = { 0, "", "" }; + uint32_t nextlogical; + struct STAT statbuf; + int status; + FILE* logFile; + int result; + + // + // Verify that the log file has a non-zero size. + // + // NOTE: We prefer stat64 because some of the coverage files are HUGE! + status = STAT( file, &statbuf ); + if (status == -1) { + fprintf( stderr, "Unable to stat %s\n", file ); + return false; + } + + if (statbuf.st_size == 0) { + fprintf( stderr, "%s is 0 bytes long\n", file ); + return false; + } + + // + // Open the coverage file and discard the header. + // + logFile = OPEN( file, "r" ); + if (!logFile) { + fprintf( stderr, "Unable to open %s\n", file ); + return false; + } + + + // + // Discard Header section + // + if (! ReadUntilFound( logFile, QEMU_LOG_SECTION_END ) ) { + fprintf( stderr, "Unable to locate end of log file header\n" ); + return false; + } + + // + // Find first IN block + // + if (! ReadUntilFound( logFile, QEMU_LOG_IN_KEY )){ + fprintf(stderr,"Error: Unable to locate first IN: Block in Log file \n"); + return false; + } + + // + // Read First Start Address + // + fgets(inputBuffer, MAX_LINE_LENGTH, logFile ); + result = sscanf( + inputBuffer, + "0x%08lx: %s %s\n", + &first.address, + first.instruction, + first.data + ); + if ( result < 2 ) + { + fprintf(stderr, "Error Unable to Read Initial First Block\n" ); + done = true; + } + + while (!done) { + + last = first; + + // Read until we get to the last instruction in the block. + do { + fgets(inputBuffer, MAX_LINE_LENGTH, logFile ); + result = sscanf( + inputBuffer, + "0x%08lx: %s %s\n", + &last.address, + last.instruction, + last.data + ); + } while( result > 1); + + nextlogical = objdumpProcessor->getAddressAfter(last.address); + + if (! ReadUntilFound( logFile, QEMU_LOG_IN_KEY )) { + done = true; + nextExecuted = last; + } else { + fgets(inputBuffer, MAX_LINE_LENGTH, logFile ); + result = sscanf( + inputBuffer, + "0x%08lx: %s %s\n", + &nextExecuted.address, + nextExecuted.instruction, + nextExecuted.data + ); + if ( result < 2 ) + { + fprintf(stderr, "Error Unable to Read First Block\n" ); + } + } + + // If the nextlogical was not found we are throwing away + // the block; otherwise add the block to the trace list. + if (nextlogical != 0) { + TraceList::exitReason_t reason = TraceList::EXIT_REASON_OTHER; + + if ( objdumpProcessor->IsBranch( last.instruction ) ) { + if ( nextExecuted.address == nextlogical ) { + reason = TraceList::EXIT_REASON_BRANCH_NOT_TAKEN; + } else { + reason = TraceList::EXIT_REASON_BRANCH_TAKEN; + } + } + Trace.add( first.address, nextlogical, reason ); + } + first = nextExecuted; + } + fclose( logFile ); + return true; + } +} |