nativetrace.cc revision 4776:8c8407243a2c
1/*
2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Steve Reinhardt
29 *          Lisa Hsu
30 *          Nathan Binkert
31 *          Steve Raasch
32 */
33
34#include <errno.h>
35
36#include "arch/regfile.hh"
37#include "arch/utility.hh"
38#include "base/loader/symtab.hh"
39#include "base/socket.hh"
40#include "cpu/nativetrace.hh"
41#include "cpu/static_inst.hh"
42#include "cpu/thread_context.hh"
43#include "params/NativeTrace.hh"
44
45//XXX This is temporary
46#include "arch/isa_specific.hh"
47
48using namespace std;
49using namespace TheISA;
50
51namespace Trace {
52
53NativeTrace::NativeTrace(const std::string & _name) : InstTracer(_name)
54{
55    int port = 8000;
56    while(!native_listener.listen(port, true))
57    {
58        DPRINTF(GDBMisc, "Can't bind port %d\n", port);
59        port++;
60    }
61    ccprintf(cerr, "Listening for native process on port %d\n", port);
62    fd = native_listener.accept();
63}
64
65bool
66NativeTraceRecord::checkIntReg(const char * regName, int index, int size)
67{
68    uint64_t regVal;
69    int res = read(parent->fd, &regVal, size);
70    if(res < 0)
71        panic("Read call failed! %s\n", strerror(errno));
72    regVal = TheISA::gtoh(regVal);
73    uint64_t realRegVal = thread->readIntReg(index);
74    if(regVal != realRegVal)
75    {
76        DPRINTFN("Register %s should be %#x but is %#x.\n",
77                regName, regVal, realRegVal);
78        return false;
79    }
80    return true;
81}
82
83bool NativeTraceRecord::checkPC(const char * regName, int size)
84{
85    uint64_t regVal;
86    int res = read(parent->fd, &regVal, size);
87    if(res < 0)
88        panic("Read call failed! %s\n", strerror(errno));
89    regVal = TheISA::gtoh(regVal);
90    uint64_t realRegVal = thread->readNextPC();
91    if(regVal != realRegVal)
92    {
93        DPRINTFN("%s should be %#x but is %#x.\n",
94                regName, regVal, realRegVal);
95        return false;
96    }
97    return true;
98}
99
100void
101Trace::NativeTraceRecord::dump()
102{
103//    ostream &outs = Trace::output();
104
105    //Don't print what happens for each micro-op, just print out
106    //once at the last op, and for regular instructions.
107    if(!staticInst->isMicroop() || staticInst->isLastMicroop())
108    {
109        checkIntReg("rax", INTREG_RAX, sizeof(uint64_t));
110        checkIntReg("rbx", INTREG_RBX, sizeof(uint64_t));
111        checkIntReg("rcx", INTREG_RCX, sizeof(uint64_t));
112        checkIntReg("rdx", INTREG_RDX, sizeof(uint64_t));
113        checkIntReg("rsp", INTREG_RSP, sizeof(uint64_t));
114        checkIntReg("rbp", INTREG_RBP, sizeof(uint64_t));
115        checkIntReg("rsi", INTREG_RSI, sizeof(uint64_t));
116        checkIntReg("rdi", INTREG_RDI, sizeof(uint64_t));
117        checkIntReg("r8", INTREG_R8, sizeof(uint64_t));
118        checkIntReg("r9", INTREG_R9, sizeof(uint64_t));
119        checkIntReg("r10", INTREG_R10, sizeof(uint64_t));
120        checkIntReg("r11", INTREG_R11, sizeof(uint64_t));
121        checkIntReg("r12", INTREG_R12, sizeof(uint64_t));
122        checkIntReg("r13", INTREG_R13, sizeof(uint64_t));
123        checkIntReg("r14", INTREG_R14, sizeof(uint64_t));
124        checkIntReg("r15", INTREG_R15, sizeof(uint64_t));
125        checkPC("rip", sizeof(uint64_t));
126#if THE_ISA == SPARC_ISA
127        /*for(int f = 0; f <= 62; f+=2)
128        {
129            uint64_t regVal;
130            int res = read(fd, &regVal, sizeof(regVal));
131            if(res < 0)
132                panic("First read call failed! %s\n", strerror(errno));
133            regVal = TheISA::gtoh(regVal);
134            uint64_t realRegVal = thread->readFloatRegBits(f, 64);
135            if(regVal != realRegVal)
136            {
137                DPRINTF(ExecRegDelta, "Register f%d should be %#x but is %#x.\n", f, regVal, realRegVal);
138            }
139        }*/
140        uint64_t regVal;
141        int res = read(fd, &regVal, sizeof(regVal));
142        if(res < 0)
143            panic("First read call failed! %s\n", strerror(errno));
144        regVal = TheISA::gtoh(regVal);
145        uint64_t realRegVal = thread->readNextPC();
146        if(regVal != realRegVal)
147        {
148            DPRINTF(ExecRegDelta,
149                    "Register pc should be %#x but is %#x.\n",
150                    regVal, realRegVal);
151        }
152        res = read(fd, &regVal, sizeof(regVal));
153        if(res < 0)
154            panic("First read call failed! %s\n", strerror(errno));
155        regVal = TheISA::gtoh(regVal);
156        realRegVal = thread->readNextNPC();
157        if(regVal != realRegVal)
158        {
159            DPRINTF(ExecRegDelta,
160                    "Register npc should be %#x but is %#x.\n",
161                    regVal, realRegVal);
162        }
163        res = read(fd, &regVal, sizeof(regVal));
164        if(res < 0)
165            panic("First read call failed! %s\n", strerror(errno));
166        regVal = TheISA::gtoh(regVal);
167        realRegVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2);
168        if((regVal & 0xF) != (realRegVal & 0xF))
169        {
170            DPRINTF(ExecRegDelta,
171                    "Register ccr should be %#x but is %#x.\n",
172                    regVal, realRegVal);
173        }
174#endif
175    }
176}
177
178/* namespace Trace */ }
179
180////////////////////////////////////////////////////////////////////////
181//
182//  ExeTracer Simulation Object
183//
184Trace::NativeTrace *
185NativeTraceParams::create()
186{
187    return new Trace::NativeTrace(name);
188};
189