source: rtems-tools/tester/covoar/TraceReaderLogQEMU.cc @ f9a4b2c

5
Last change on this file since f9a4b2c was 6a4859e, checked in by Cillian O'Donnell <cpodonnell8@…>, on 08/26/17 at 08:15:56

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.

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2 * RTEMS Tools Project (http://www.rtems.org/)
3 * Copyright 2014 OAR Corporation
4 * All rights reserved.
5 *
6 * This file is part of the RTEMS Tools package in 'rtems-tools'.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/*! @file TraceReaderLogQEMU.cc
32 *  @brief TraceReaderLogQEMU Implementation
33 *
34 *  This file contains the implementation of the functions supporting
35 *  reading the QEMU coverage data files.
36 */
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <sys/stat.h>
41#include <string.h>
42
43#include "qemu-log.h"
44#include "app_common.h"
45#include "TraceReaderBase.h"
46#include "TraceReaderLogQEMU.h"
47#include "TraceList.h"
48#include "qemu-traces.h"
49
50#include "rld-process.h"
51
52#if HAVE_STAT64
53#define STAT stat64
54#else
55#define STAT stat
56#endif
57
58#if HAVE_OPEN64
59#define OPEN fopen64
60#else
61#define OPEN fopen
62#endif
63
64namespace Trace {
65
66  TraceReaderLogQEMU::TraceReaderLogQEMU()
67  {
68  }
69
70  TraceReaderLogQEMU::~TraceReaderLogQEMU()
71  {
72  }
73
74  bool TraceReaderLogQEMU::processFile(
75    const char* const     file
76  )
77  {
78    bool                done          = false;
79    QEMU_LOG_IN_Block_t first         = { 0, "", "" };
80    QEMU_LOG_IN_Block_t last          = { 0, "", "" };
81    QEMU_LOG_IN_Block_t nextExecuted  = { 0, "", "" };
82    uint32_t            nextlogical;
83    struct STAT         statbuf;
84    int                 status;
85    FILE*               logFile;
86    int                 result;
87
88    //
89    // Verify that the log file has a non-zero size.
90    //
91    // NOTE: We prefer stat64 because some of the coverage files are HUGE!
92    status = STAT( file, &statbuf );
93    if (status == -1) {
94      fprintf( stderr, "Unable to stat %s\n", file );
95      return false;
96    }
97
98    if (statbuf.st_size == 0) {
99      fprintf( stderr, "%s is 0 bytes long\n", file );
100      return false;
101    }
102
103    //
104    // Open the coverage file and discard the header.
105    //
106    logFile = OPEN( file, "r" );
107    if (!logFile) {
108      fprintf( stderr, "Unable to open %s\n", file );
109      return false;
110    }
111
112
113    //
114    //  Discard Header section
115    //
116    if (! ReadUntilFound( logFile, QEMU_LOG_SECTION_END ) ) {
117      fprintf( stderr, "Unable to locate end of log file header\n" );
118      return false;
119    }
120
121    //
122    //  Find first IN block
123    //
124    if (! ReadUntilFound( logFile, QEMU_LOG_IN_KEY )){
125      fprintf(stderr,"Error: Unable to locate first IN: Block in Log file \n");
126      return false;
127    }
128
129    //
130    //  Read First Start Address
131    //
132    fgets(inputBuffer, MAX_LINE_LENGTH, logFile );
133    result = sscanf(
134      inputBuffer,
135      "0x%08lx: %s %s\n",
136      &first.address,
137      first.instruction,
138      first.data
139    );
140    if ( result < 2 )
141    {
142      fprintf(stderr, "Error Unable to Read Initial First Block\n" );
143      done = true;
144    }
145
146    while (!done) {
147
148      last = first;
149
150      // Read until we get to the last instruction in the block.
151      do {
152        fgets(inputBuffer, MAX_LINE_LENGTH, logFile );
153        result = sscanf(
154          inputBuffer,
155          "0x%08lx: %s %s\n",
156          &last.address,
157          last.instruction,
158          last.data
159        );
160      } while( result > 1);
161
162      nextlogical = objdumpProcessor->getAddressAfter(last.address);
163
164      if (! ReadUntilFound( logFile, QEMU_LOG_IN_KEY )) {
165        done = true;
166        nextExecuted = last;
167      } else {
168        fgets(inputBuffer, MAX_LINE_LENGTH, logFile );
169        result = sscanf(
170          inputBuffer,
171          "0x%08lx: %s %s\n",
172          &nextExecuted.address,
173          nextExecuted.instruction,
174          nextExecuted.data
175        );
176        if ( result < 2 )
177        {
178          fprintf(stderr, "Error Unable to Read First Block\n" );
179        }
180      }
181
182      // If the nextlogical was not found we are throwing away
183      // the block; otherwise add the block to the trace list.
184      if (nextlogical != 0) {
185        TraceList::exitReason_t reason = TraceList::EXIT_REASON_OTHER;
186
187        if ( objdumpProcessor->IsBranch( last.instruction ) ) {
188          if ( nextExecuted.address == nextlogical ) {
189            reason = TraceList::EXIT_REASON_BRANCH_NOT_TAKEN;
190          }  else {
191            reason = TraceList::EXIT_REASON_BRANCH_TAKEN;
192          }
193        }
194        Trace.add( first.address, nextlogical, reason );
195      }
196      first = nextExecuted;
197    }
198    fclose( logFile );
199    return true;
200  }
201}
Note: See TracBrowser for help on using the repository browser.