Adding gem5 source to svn.
git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1819 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
39
simulators/gem5/util/statetrace/SConscript
Normal file
39
simulators/gem5/util/statetrace/SConscript
Normal file
@ -0,0 +1,39 @@
|
||||
# Copyright (c) 2011 Gabe Black
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met: redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer;
|
||||
# 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;
|
||||
# neither the name of the copyright holders nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# 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
|
||||
# OWNER 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.
|
||||
#
|
||||
# Authors: Gabe Black
|
||||
|
||||
import os
|
||||
|
||||
Import('env', 'arch')
|
||||
|
||||
env.Append(CPPPATH=Dir('.'))
|
||||
|
||||
sources = [os.path.join('base', 'statetrace.cc'),
|
||||
os.path.join('base', 'tracechild.cc'),
|
||||
os.path.join('arch', arch, 'tracechild.cc')]
|
||||
objects = [env.Object(source) for source in sources]
|
||||
env.Program('statetrace', objects)
|
||||
67
simulators/gem5/util/statetrace/SConstruct
Normal file
67
simulators/gem5/util/statetrace/SConstruct
Normal file
@ -0,0 +1,67 @@
|
||||
# Copyright (c) 2011 Gabe Black
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met: redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer;
|
||||
# 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;
|
||||
# neither the name of the copyright holders nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# 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
|
||||
# OWNER 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.
|
||||
#
|
||||
# Authors: Gabe Black
|
||||
|
||||
Help('''
|
||||
To build a version of statetrace suitable to run on a particular ISA, use a
|
||||
target of the form build/<arch>/statetrace. For example, to build statetrace
|
||||
for ARM binaries, run:
|
||||
|
||||
scons build/arm/statetrace
|
||||
|
||||
You may need a cross compiler in order to build statetrace successfully. To
|
||||
specify an alternative compiler, set the CXX scons argument on the command
|
||||
line. The CXX environment variable is NOT considered when selecting the
|
||||
compiler. To override the compiler for a particular target ISA, set the
|
||||
<arch>CXX scons argument. For example, to build both the AMD64 version and
|
||||
the ARM version at the same time using the system compiler for the AMD64
|
||||
version and a cross compiler for arm, your command line would look like the
|
||||
following:
|
||||
|
||||
scons ARMCXX=arm-cross-g++ build/amd64/statetrace build/arm/statetrace
|
||||
|
||||
After a successful build, the statetrace binary(binaries) will be located in
|
||||
the build/<arch>/ directories you specified on the command line.
|
||||
''')
|
||||
|
||||
|
||||
arches = 'amd64', 'arm', 'i686', 'sparc'
|
||||
|
||||
import os
|
||||
|
||||
main = Environment()
|
||||
main.SetOption('duplicate', 'soft-copy')
|
||||
main['CXXFLAGS'] = "-O3 -ggdb $_CPPINCFLAGS"
|
||||
|
||||
main['CXX'] = ARGUMENTS.get('CXX', main['CXX'])
|
||||
|
||||
for arch in arches:
|
||||
env = main.Clone()
|
||||
env['CXX'] = ARGUMENTS.get(arch.upper() + 'CXX', env['CXX'])
|
||||
env.Append(CPPFLAGS = '-D__STATETRACE_%s__' % arch.upper())
|
||||
Export('env', 'arch')
|
||||
env.SConscript('SConscript', variant_dir = os.path.join('build', arch))
|
||||
405
simulators/gem5/util/statetrace/arch/amd64/tracechild.cc
Normal file
405
simulators/gem5/util/statetrace/arch/amd64/tracechild.cc
Normal file
@ -0,0 +1,405 @@
|
||||
/*
|
||||
* Copyright (c) 2007 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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
|
||||
* OWNER 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.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
#include "arch/amd64/tracechild.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool
|
||||
AMD64TraceChild::sendState(int socket)
|
||||
{
|
||||
uint64_t regVal64 = 0;
|
||||
uint32_t regVal32 = 0;
|
||||
for (int x = 0; x <= R15; x++) {
|
||||
regVal64 = getRegVal(x);
|
||||
if (write(socket, ®Val64, sizeof(regVal64)) == -1) {
|
||||
cerr << "Write failed! " << strerror(errno) << endl;
|
||||
tracing = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
regVal64 = getRegVal(RIP);
|
||||
if (write(socket, ®Val64, sizeof(regVal64)) == -1) {
|
||||
cerr << "Write failed! " << strerror(errno) << endl;
|
||||
tracing = false;
|
||||
return false;
|
||||
}
|
||||
for (int x = MMX0_0; x <= MMX7_1; x++) {
|
||||
regVal32 = getRegVal(x);
|
||||
if (write(socket, ®Val32, sizeof(regVal32)) == -1) {
|
||||
cerr << "Write failed! " << strerror(errno) << endl;
|
||||
tracing = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int x = XMM0_0; x <= XMM15_3; x++) {
|
||||
regVal32 = getRegVal(x);
|
||||
if (write(socket, ®Val32, sizeof(regVal32)) == -1) {
|
||||
cerr << "Write failed! " << strerror(errno) << endl;
|
||||
tracing = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t
|
||||
AMD64TraceChild::getRegs(user_regs_struct & myregs,
|
||||
user_fpregs_struct & myfpregs, int num)
|
||||
{
|
||||
assert(num < numregs && num >= 0);
|
||||
switch (num) {
|
||||
//GPRs
|
||||
case RAX: return myregs.rax;
|
||||
case RBX: return myregs.rbx;
|
||||
case RCX: return myregs.rcx;
|
||||
case RDX: return myregs.rdx;
|
||||
//Index registers
|
||||
case RSI: return myregs.rsi;
|
||||
case RDI: return myregs.rdi;
|
||||
//Base pointer and stack pointer
|
||||
case RBP: return myregs.rbp;
|
||||
case RSP: return myregs.rsp;
|
||||
//New 64 bit mode registers
|
||||
case R8: return myregs.r8;
|
||||
case R9: return myregs.r9;
|
||||
case R10: return myregs.r10;
|
||||
case R11: return myregs.r11;
|
||||
case R12: return myregs.r12;
|
||||
case R13: return myregs.r13;
|
||||
case R14: return myregs.r14;
|
||||
case R15: return myregs.r15;
|
||||
//Segmentation registers
|
||||
case CS: return myregs.cs;
|
||||
case DS: return myregs.ds;
|
||||
case ES: return myregs.es;
|
||||
case FS: return myregs.fs;
|
||||
case GS: return myregs.gs;
|
||||
case SS: return myregs.ss;
|
||||
case FS_BASE: return myregs.fs_base;
|
||||
case GS_BASE: return myregs.gs_base;
|
||||
//PC
|
||||
case RIP: return myregs.rip;
|
||||
//Flags
|
||||
case EFLAGS: return myregs.eflags;
|
||||
//MMX
|
||||
case MMX0_0: return myfpregs.st_space[0];
|
||||
case MMX0_1: return myfpregs.st_space[1];
|
||||
case MMX1_0: return myfpregs.st_space[2];
|
||||
case MMX1_1: return myfpregs.st_space[3];
|
||||
case MMX2_0: return myfpregs.st_space[4];
|
||||
case MMX2_1: return myfpregs.st_space[5];
|
||||
case MMX3_0: return myfpregs.st_space[6];
|
||||
case MMX3_1: return myfpregs.st_space[7];
|
||||
case MMX4_0: return myfpregs.st_space[8];
|
||||
case MMX4_1: return myfpregs.st_space[9];
|
||||
case MMX5_0: return myfpregs.st_space[10];
|
||||
case MMX5_1: return myfpregs.st_space[11];
|
||||
case MMX6_0: return myfpregs.st_space[12];
|
||||
case MMX6_1: return myfpregs.st_space[13];
|
||||
case MMX7_0: return myfpregs.st_space[14];
|
||||
case MMX7_1: return myfpregs.st_space[15];
|
||||
//XMM
|
||||
case XMM0_0: return myfpregs.xmm_space[0];
|
||||
case XMM0_1: return myfpregs.xmm_space[1];
|
||||
case XMM0_2: return myfpregs.xmm_space[2];
|
||||
case XMM0_3: return myfpregs.xmm_space[3];
|
||||
case XMM1_0: return myfpregs.xmm_space[4];
|
||||
case XMM1_1: return myfpregs.xmm_space[5];
|
||||
case XMM1_2: return myfpregs.xmm_space[6];
|
||||
case XMM1_3: return myfpregs.xmm_space[7];
|
||||
case XMM2_0: return myfpregs.xmm_space[8];
|
||||
case XMM2_1: return myfpregs.xmm_space[9];
|
||||
case XMM2_2: return myfpregs.xmm_space[10];
|
||||
case XMM2_3: return myfpregs.xmm_space[11];
|
||||
case XMM3_0: return myfpregs.xmm_space[12];
|
||||
case XMM3_1: return myfpregs.xmm_space[13];
|
||||
case XMM3_2: return myfpregs.xmm_space[14];
|
||||
case XMM3_3: return myfpregs.xmm_space[15];
|
||||
case XMM4_0: return myfpregs.xmm_space[16];
|
||||
case XMM4_1: return myfpregs.xmm_space[17];
|
||||
case XMM4_2: return myfpregs.xmm_space[18];
|
||||
case XMM4_3: return myfpregs.xmm_space[19];
|
||||
case XMM5_0: return myfpregs.xmm_space[20];
|
||||
case XMM5_1: return myfpregs.xmm_space[21];
|
||||
case XMM5_2: return myfpregs.xmm_space[22];
|
||||
case XMM5_3: return myfpregs.xmm_space[23];
|
||||
case XMM6_0: return myfpregs.xmm_space[24];
|
||||
case XMM6_1: return myfpregs.xmm_space[25];
|
||||
case XMM6_2: return myfpregs.xmm_space[26];
|
||||
case XMM6_3: return myfpregs.xmm_space[27];
|
||||
case XMM7_0: return myfpregs.xmm_space[28];
|
||||
case XMM7_1: return myfpregs.xmm_space[29];
|
||||
case XMM7_2: return myfpregs.xmm_space[30];
|
||||
case XMM7_3: return myfpregs.xmm_space[31];
|
||||
case XMM8_0: return myfpregs.xmm_space[32];
|
||||
case XMM8_1: return myfpregs.xmm_space[33];
|
||||
case XMM8_2: return myfpregs.xmm_space[34];
|
||||
case XMM8_3: return myfpregs.xmm_space[35];
|
||||
case XMM9_0: return myfpregs.xmm_space[36];
|
||||
case XMM9_1: return myfpregs.xmm_space[37];
|
||||
case XMM9_2: return myfpregs.xmm_space[38];
|
||||
case XMM9_3: return myfpregs.xmm_space[39];
|
||||
case XMM10_0: return myfpregs.xmm_space[40];
|
||||
case XMM10_1: return myfpregs.xmm_space[41];
|
||||
case XMM10_2: return myfpregs.xmm_space[42];
|
||||
case XMM10_3: return myfpregs.xmm_space[43];
|
||||
case XMM11_0: return myfpregs.xmm_space[44];
|
||||
case XMM11_1: return myfpregs.xmm_space[45];
|
||||
case XMM11_2: return myfpregs.xmm_space[46];
|
||||
case XMM11_3: return myfpregs.xmm_space[47];
|
||||
case XMM12_0: return myfpregs.xmm_space[48];
|
||||
case XMM12_1: return myfpregs.xmm_space[49];
|
||||
case XMM12_2: return myfpregs.xmm_space[50];
|
||||
case XMM12_3: return myfpregs.xmm_space[51];
|
||||
case XMM13_0: return myfpregs.xmm_space[52];
|
||||
case XMM13_1: return myfpregs.xmm_space[53];
|
||||
case XMM13_2: return myfpregs.xmm_space[54];
|
||||
case XMM13_3: return myfpregs.xmm_space[55];
|
||||
case XMM14_0: return myfpregs.xmm_space[56];
|
||||
case XMM14_1: return myfpregs.xmm_space[57];
|
||||
case XMM14_2: return myfpregs.xmm_space[58];
|
||||
case XMM14_3: return myfpregs.xmm_space[59];
|
||||
case XMM15_0: return myfpregs.xmm_space[60];
|
||||
case XMM15_1: return myfpregs.xmm_space[61];
|
||||
case XMM15_2: return myfpregs.xmm_space[62];
|
||||
case XMM15_3: return myfpregs.xmm_space[63];
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
AMD64TraceChild::update(int pid)
|
||||
{
|
||||
oldregs = regs;
|
||||
oldfpregs = fpregs;
|
||||
if (ptrace(PTRACE_GETREGS, pid, 0, ®s) != 0) {
|
||||
cerr << "update: " << strerror(errno) << endl;
|
||||
return false;
|
||||
}
|
||||
if (ptrace(PTRACE_GETFPREGS, pid, 0, &fpregs) != 0) {
|
||||
cerr << "update: " << strerror(errno) << endl;
|
||||
return false;
|
||||
}
|
||||
for (unsigned int x = 0; x < numregs; x++)
|
||||
regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
|
||||
return true;
|
||||
}
|
||||
|
||||
AMD64TraceChild::AMD64TraceChild()
|
||||
{
|
||||
for (unsigned int x = 0; x < numregs; x++)
|
||||
regDiffSinceUpdate[x] = false;
|
||||
}
|
||||
|
||||
int64_t
|
||||
AMD64TraceChild::getRegVal(int num)
|
||||
{
|
||||
return getRegs(regs, fpregs, num);
|
||||
}
|
||||
|
||||
int64_t
|
||||
AMD64TraceChild::getOldRegVal(int num)
|
||||
{
|
||||
return getRegs(oldregs, oldfpregs, num);
|
||||
}
|
||||
|
||||
ostream &
|
||||
AMD64TraceChild::outputStartState(ostream & os)
|
||||
{
|
||||
uint64_t sp = getSP();
|
||||
uint64_t pc = getPC();
|
||||
uint64_t highestInfo = 0;
|
||||
char obuf[1024];
|
||||
sprintf(obuf, "Initial stack pointer = 0x%016lx\n", sp);
|
||||
os << obuf;
|
||||
sprintf(obuf, "Initial program counter = 0x%016lx\n", pc);
|
||||
os << obuf;
|
||||
|
||||
//Output the argument count
|
||||
uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
sprintf(obuf, "0x%016lx: Argc = 0x%016lx\n", sp, cargc);
|
||||
os << obuf;
|
||||
sp += 8;
|
||||
|
||||
//Output argv pointers
|
||||
int argCount = 0;
|
||||
uint64_t cargv;
|
||||
do {
|
||||
cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
sprintf(obuf, "0x%016lx: argv[%d] = 0x%016lx\n",
|
||||
sp, argCount++, cargv);
|
||||
if (cargv)
|
||||
if (highestInfo < cargv)
|
||||
highestInfo = cargv;
|
||||
os << obuf;
|
||||
sp += 8;
|
||||
} while(cargv);
|
||||
|
||||
//Output the envp pointers
|
||||
int envCount = 0;
|
||||
uint64_t cenvp;
|
||||
do {
|
||||
cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
sprintf(obuf, "0x%016lx: envp[%d] = 0x%016lx\n",
|
||||
sp, envCount++, cenvp);
|
||||
os << obuf;
|
||||
sp += 8;
|
||||
} while(cenvp);
|
||||
uint64_t auxType, auxVal;
|
||||
do {
|
||||
auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
sp += 8;
|
||||
auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
sp += 8;
|
||||
sprintf(obuf, "0x%016lx: Auxiliary vector = {0x%016lx, 0x%016lx}\n",
|
||||
sp - 16, auxType, auxVal);
|
||||
os << obuf;
|
||||
} while(auxType != 0 || auxVal != 0);
|
||||
//Print out the argument strings, environment strings, and file name.
|
||||
string current;
|
||||
uint64_t buf;
|
||||
uint64_t currentStart = sp;
|
||||
bool clearedInitialPadding = false;
|
||||
do {
|
||||
buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
char * cbuf = (char *)&buf;
|
||||
for (int x = 0; x < sizeof(uint64_t); x++) {
|
||||
if (cbuf[x])
|
||||
current += cbuf[x];
|
||||
else {
|
||||
sprintf(obuf, "0x%016lx: \"%s\"\n",
|
||||
currentStart, current.c_str());
|
||||
os << obuf;
|
||||
current = "";
|
||||
currentStart = sp + x + 1;
|
||||
}
|
||||
}
|
||||
sp += 8;
|
||||
clearedInitialPadding = clearedInitialPadding || buf != 0;
|
||||
} while (!clearedInitialPadding || buf != 0 || sp <= highestInfo);
|
||||
return os;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
AMD64TraceChild::findSyscall()
|
||||
{
|
||||
uint64_t rip = getPC();
|
||||
bool foundOpcode = false;
|
||||
bool twoByteOpcode = false;
|
||||
for (;;) {
|
||||
uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, rip, 0);
|
||||
for (int i = 0; i < sizeof(uint64_t); i++) {
|
||||
unsigned char byte = buf & 0xFF;
|
||||
if (!foundOpcode) {
|
||||
if(!(byte == 0x66 || //operand override
|
||||
byte == 0x67 || //address override
|
||||
byte == 0x2E || //cs
|
||||
byte == 0x3E || //ds
|
||||
byte == 0x26 || //es
|
||||
byte == 0x64 || //fs
|
||||
byte == 0x65 || //gs
|
||||
byte == 0x36 || //ss
|
||||
byte == 0xF0 || //lock
|
||||
byte == 0xF2 || //repe
|
||||
byte == 0xF3 || //repne
|
||||
(byte >= 0x40 && byte <= 0x4F) // REX
|
||||
)) {
|
||||
foundOpcode = true;
|
||||
}
|
||||
}
|
||||
if (foundOpcode) {
|
||||
if (twoByteOpcode) {
|
||||
//SYSCALL or SYSENTER
|
||||
if (byte == 0x05 || byte == 0x34)
|
||||
return rip + 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
if (!twoByteOpcode) {
|
||||
if (byte == 0xCC) // INT3
|
||||
return rip + 1;
|
||||
else if (byte == 0xCD) // INT with byte immediate
|
||||
return rip + 2;
|
||||
else if (byte == 0x0F) // two byte opcode prefix
|
||||
twoByteOpcode = true;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
buf >>= 8;
|
||||
rip++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
AMD64TraceChild::step()
|
||||
{
|
||||
uint64_t ripAfterSyscall = findSyscall();
|
||||
if (ripAfterSyscall) {
|
||||
//Get the original contents of memory
|
||||
uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, ripAfterSyscall, 0);
|
||||
//Patch the first two bytes of the memory immediately after this with
|
||||
//jmp -2. Either single stepping will take over before this
|
||||
//instruction, leaving the rip where it should be, or it will take
|
||||
//over after this instruction, -still- leaving the rip where it should
|
||||
//be.
|
||||
uint64_t newBuf = (buf & ~0xFFFF) | 0xFEEB;
|
||||
//Write the patched memory to the processes address space
|
||||
ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, newBuf);
|
||||
//Step and hit it
|
||||
ptraceSingleStep();
|
||||
//Put things back to the way they started
|
||||
ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, buf);
|
||||
} else {
|
||||
//Get all the way past repe and repne string instructions in one shot.
|
||||
uint64_t newPC, origPC = getPC();
|
||||
do {
|
||||
ptraceSingleStep();
|
||||
newPC = getPC();
|
||||
} while(newPC == origPC);
|
||||
}
|
||||
}
|
||||
|
||||
TraceChild * genTraceChild()
|
||||
{
|
||||
return new AMD64TraceChild;
|
||||
}
|
||||
119
simulators/gem5/util/statetrace/arch/amd64/tracechild.hh
Normal file
119
simulators/gem5/util/statetrace/arch/amd64/tracechild.hh
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2007 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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
|
||||
* OWNER 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.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#ifndef REGSTATE_AMD64_HH
|
||||
#define REGSTATE_AMD64_HH
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include "base/tracechild.hh"
|
||||
|
||||
class AMD64TraceChild : public TraceChild
|
||||
{
|
||||
public:
|
||||
enum RegNum
|
||||
{
|
||||
//GPRs
|
||||
RAX, RCX, RDX, RBX,
|
||||
//Base pointer and stack pointer
|
||||
RSP, RBP,
|
||||
//Index registers
|
||||
RSI, RDI,
|
||||
//New 64 bit mode registers
|
||||
R8, R9, R10, R11, R12, R13, R14, R15,
|
||||
//Segmentation registers
|
||||
CS, DS, ES, FS, GS, SS, FS_BASE, GS_BASE,
|
||||
//PC
|
||||
RIP,
|
||||
//Flags
|
||||
EFLAGS,
|
||||
//MMX
|
||||
MMX0_0, MMX0_1,
|
||||
MMX1_0, MMX1_1,
|
||||
MMX2_0, MMX2_1,
|
||||
MMX3_0, MMX3_1,
|
||||
MMX4_0, MMX4_1,
|
||||
MMX5_0, MMX5_1,
|
||||
MMX6_0, MMX6_1,
|
||||
MMX7_0, MMX7_1,
|
||||
//XMM
|
||||
XMM0_0, XMM0_1, XMM0_2, XMM0_3,
|
||||
XMM1_0, XMM1_1, XMM1_2, XMM1_3,
|
||||
XMM2_0, XMM2_1, XMM2_2, XMM2_3,
|
||||
XMM3_0, XMM3_1, XMM3_2, XMM3_3,
|
||||
XMM4_0, XMM4_1, XMM4_2, XMM4_3,
|
||||
XMM5_0, XMM5_1, XMM5_2, XMM5_3,
|
||||
XMM6_0, XMM6_1, XMM6_2, XMM6_3,
|
||||
XMM7_0, XMM7_1, XMM7_2, XMM7_3,
|
||||
XMM8_0, XMM8_1, XMM8_2, XMM8_3,
|
||||
XMM9_0, XMM9_1, XMM9_2, XMM9_3,
|
||||
XMM10_0, XMM10_1, XMM10_2, XMM10_3,
|
||||
XMM11_0, XMM11_1, XMM11_2, XMM11_3,
|
||||
XMM12_0, XMM12_1, XMM12_2, XMM12_3,
|
||||
XMM13_0, XMM13_1, XMM13_2, XMM13_3,
|
||||
XMM14_0, XMM14_1, XMM14_2, XMM14_3,
|
||||
XMM15_0, XMM15_1, XMM15_2, XMM15_3,
|
||||
numregs
|
||||
};
|
||||
private:
|
||||
int64_t getRegs(user_regs_struct & myregs,
|
||||
user_fpregs_struct &myfpregs,int num);
|
||||
user_regs_struct regs;
|
||||
user_regs_struct oldregs;
|
||||
user_fpregs_struct fpregs;
|
||||
user_fpregs_struct oldfpregs;
|
||||
bool regDiffSinceUpdate[numregs];
|
||||
|
||||
uint64_t findSyscall();
|
||||
|
||||
protected:
|
||||
bool update(int pid);
|
||||
|
||||
public:
|
||||
|
||||
AMD64TraceChild();
|
||||
|
||||
bool sendState(int socket);
|
||||
|
||||
int64_t getRegVal(int num);
|
||||
int64_t getOldRegVal(int num);
|
||||
uint64_t getPC() {return getRegVal(RIP);}
|
||||
uint64_t getSP() {return getRegVal(RSP);}
|
||||
std::ostream & outputStartState(std::ostream & output);
|
||||
|
||||
bool step();
|
||||
};
|
||||
|
||||
#endif
|
||||
286
simulators/gem5/util/statetrace/arch/arm/tracechild.cc
Normal file
286
simulators/gem5/util/statetrace/arch/arm/tracechild.cc
Normal file
@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2006-2009 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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
|
||||
* OWNER 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.
|
||||
*
|
||||
* Authors: Ali Saidi
|
||||
* Gabe Black
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#include "arch/arm/tracechild.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
ARMTraceChild::ARMTraceChild()
|
||||
{
|
||||
foundMvn = false;
|
||||
|
||||
memset(®s, 0, sizeof(regs));
|
||||
memset(&oldregs, 0, sizeof(regs));
|
||||
memset(&fpregs, 0, sizeof(vfp_regs));
|
||||
memset(&oldfpregs, 0, sizeof(vfp_regs));
|
||||
|
||||
for (int x = 0; x < numregs; x++) {
|
||||
regDiffSinceUpdate[x] = false;
|
||||
}
|
||||
|
||||
assert(sizeof(regs.uregs)/sizeof(regs.uregs[0]) > CPSR);
|
||||
}
|
||||
|
||||
bool
|
||||
ARMTraceChild::sendState(int socket)
|
||||
{
|
||||
uint32_t regVal = 0;
|
||||
uint64_t message[numregs + 1];
|
||||
int pos = 1;
|
||||
message[0] = 0;
|
||||
for (int x = 0; x < numregs; x++) {
|
||||
if (regDiffSinceUpdate[x]) {
|
||||
message[0] = message[0] | (1ULL << x);
|
||||
message[pos++] = getRegVal(x);
|
||||
}
|
||||
}
|
||||
|
||||
size_t sent = 0;
|
||||
size_t toSend = pos * sizeof(message[0]);
|
||||
uint8_t *messagePtr = (uint8_t *)message;
|
||||
while (toSend != 0) {
|
||||
sent = write(socket, messagePtr, toSend);
|
||||
if (sent == -1) {
|
||||
cerr << "Write failed! " << strerror(errno) << endl;
|
||||
tracing = false;
|
||||
return false;
|
||||
}
|
||||
toSend -= sent;
|
||||
messagePtr += sent;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ARMTraceChild::getRegs(user_regs &myregs, int num)
|
||||
{
|
||||
assert(num <= CPSR && num >= 0);
|
||||
return myregs.uregs[num];
|
||||
}
|
||||
|
||||
uint64_t
|
||||
ARMTraceChild::getFpRegs(vfp_regs &my_fp_regs, int num)
|
||||
{
|
||||
assert(num >= F0 && num < numregs);
|
||||
if (num == FPSCR)
|
||||
return my_fp_regs.fpscr;
|
||||
|
||||
num -= F0;
|
||||
return my_fp_regs.fpregs[num];
|
||||
}
|
||||
|
||||
bool
|
||||
ARMTraceChild::update(int pid)
|
||||
{
|
||||
oldregs = regs;
|
||||
if (ptrace(PTRACE_GETREGS, pid, 0, ®s) != 0) {
|
||||
cerr << "update: " << strerror(errno) << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint32_t get_vfp_regs = 32;
|
||||
|
||||
oldfpregs = fpregs;
|
||||
if (ptrace((__ptrace_request)get_vfp_regs, pid, 0, &fpregs) != 0) {
|
||||
cerr << "update: " << strerror(errno) << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int x = 0; x < numregs; x++)
|
||||
regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t
|
||||
ARMTraceChild::getRegVal(int num)
|
||||
{
|
||||
if (num <= CPSR)
|
||||
return getRegs(regs, num);
|
||||
else
|
||||
return (int64_t)getFpRegs(fpregs, num);
|
||||
}
|
||||
|
||||
int64_t
|
||||
ARMTraceChild::getOldRegVal(int num)
|
||||
{
|
||||
if (num <= CPSR)
|
||||
return getRegs(oldregs, num);
|
||||
else
|
||||
return (int64_t)getFpRegs(oldfpregs, num);
|
||||
}
|
||||
|
||||
ostream &
|
||||
ARMTraceChild::outputStartState(ostream & os)
|
||||
{
|
||||
uint32_t sp = getSP();
|
||||
uint32_t pc = getPC();
|
||||
uint32_t highestInfo = 0;
|
||||
char obuf[1024];
|
||||
sprintf(obuf, "Initial stack pointer = 0x%08x\n", sp);
|
||||
os << obuf;
|
||||
sprintf(obuf, "Initial program counter = 0x%08x\n", pc);
|
||||
os << obuf;
|
||||
|
||||
//Output the argument count
|
||||
int32_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
sprintf(obuf, "0x%08x: Argc = 0x%08x\n", sp, cargc);
|
||||
os << obuf;
|
||||
sp += 4;
|
||||
|
||||
//Output argv pointers
|
||||
int argCount = 0;
|
||||
int32_t cargv;
|
||||
do {
|
||||
cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
sprintf(obuf, "0x%08x: argv[%d] = 0x%08x\n",
|
||||
sp, argCount++, cargv);
|
||||
if(cargv)
|
||||
if(highestInfo < cargv)
|
||||
highestInfo = cargv;
|
||||
os << obuf;
|
||||
sp += 4;
|
||||
} while(cargv);
|
||||
|
||||
//Output the envp pointers
|
||||
int envCount = 0;
|
||||
uint32_t cenvp;
|
||||
do {
|
||||
cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
sprintf(obuf, "0x%08x: envp[%d] = 0x%08x\n",
|
||||
sp, envCount++, cenvp);
|
||||
os << obuf;
|
||||
sp += 4;
|
||||
} while(cenvp);
|
||||
uint32_t auxType, auxVal;
|
||||
do {
|
||||
auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
sp += 4;
|
||||
auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
sp += 4;
|
||||
sprintf(obuf, "0x%08x: Auxiliary vector = {0x%08x, 0x%08x}\n",
|
||||
sp - 8, auxType, auxVal);
|
||||
os << obuf;
|
||||
} while(auxType != 0 || auxVal != 0);
|
||||
//Print out the argument strings, environment strings, and file name.
|
||||
string current;
|
||||
uint32_t buf;
|
||||
uint32_t currentStart = sp;
|
||||
bool clearedInitialPadding = false;
|
||||
do {
|
||||
buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
char * cbuf = (char *)&buf;
|
||||
for (int x = 0; x < sizeof(uint32_t); x++) {
|
||||
if (cbuf[x])
|
||||
current += cbuf[x];
|
||||
else {
|
||||
sprintf(obuf, "0x%08x: \"%s\"\n",
|
||||
currentStart, current.c_str());
|
||||
os << obuf;
|
||||
current = "";
|
||||
currentStart = sp + x + 1;
|
||||
}
|
||||
}
|
||||
sp += 4;
|
||||
clearedInitialPadding = clearedInitialPadding || buf != 0;
|
||||
} while(!clearedInitialPadding || buf != 0 || sp <= highestInfo);
|
||||
return os;
|
||||
}
|
||||
|
||||
bool
|
||||
ARMTraceChild::step()
|
||||
{
|
||||
const uint32_t bkpt_inst = 0xe7f001f0;
|
||||
|
||||
uint32_t lr = getRegVal(14);
|
||||
uint32_t pc = getPC();
|
||||
uint32_t lrOp, subsOp;
|
||||
char obuf[128];
|
||||
bool patch = false;
|
||||
|
||||
// Since ARM uses software breakpoints behind the scenes, they don't work
|
||||
// in read only areas like the page of routines provided by the kernel. The
|
||||
// link register generally holds the address the process wants to the
|
||||
// kernel to return to after it's done, so we'll install a software
|
||||
// breakpoint there.
|
||||
//
|
||||
// Calls into the kernel user page always follow the form:
|
||||
// MVN ...
|
||||
// <possible MOV lr,...>
|
||||
// SUB PC, ...
|
||||
//
|
||||
// So we look for this pattern and set a breakpoint on the LR at the SUB
|
||||
// instruction.
|
||||
|
||||
|
||||
subsOp = ptrace(PTRACE_PEEKDATA, pid, pc, 0);
|
||||
if ((subsOp & 0xFFFF0FFF) == 0xe3e00a0f)
|
||||
foundMvn = true;
|
||||
|
||||
if (foundMvn && ((subsOp & 0xFFF0F000) == 0xe240f000)) {
|
||||
foundMvn = false;
|
||||
lrOp = ptrace(PTRACE_PEEKDATA, pid, lr, 0);
|
||||
ptrace(PTRACE_POKEDATA, pid, lr, bkpt_inst);
|
||||
patch = true;
|
||||
}
|
||||
ptraceSingleStep();
|
||||
|
||||
if (patch)
|
||||
ptrace(PTRACE_POKEDATA, pid, lr, lrOp);
|
||||
}
|
||||
|
||||
|
||||
TraceChild *
|
||||
genTraceChild()
|
||||
{
|
||||
return new ARMTraceChild;
|
||||
}
|
||||
|
||||
123
simulators/gem5/util/statetrace/arch/arm/tracechild.hh
Normal file
123
simulators/gem5/util/statetrace/arch/arm/tracechild.hh
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2009 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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
|
||||
* OWNER 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.
|
||||
*
|
||||
* Authors: Ali Saidi
|
||||
* Gabe Black
|
||||
*/
|
||||
|
||||
#ifndef TRACECHILD_ARM_HH
|
||||
#define TRACECHILD_ARM_HH
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include "base/tracechild.hh"
|
||||
|
||||
class ARMTraceChild : public TraceChild
|
||||
{
|
||||
public:
|
||||
enum RegNum
|
||||
{
|
||||
// r0 - r3 argument, temp, caller save
|
||||
// r4 - r10 callee save
|
||||
// r11 - FP
|
||||
// r12 - temp
|
||||
// r13 - stack
|
||||
// r14 - link
|
||||
// r15 - pc
|
||||
R0, R1, R2, R3, R4, R5, R6, R7,
|
||||
R8, R9, R10, FP, R12, SP, LR, PC,
|
||||
CPSR,
|
||||
F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15,
|
||||
F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29,
|
||||
F30, F31, FPSCR,
|
||||
numregs
|
||||
};
|
||||
|
||||
struct vfp_regs {
|
||||
uint64_t fpregs[32];
|
||||
uint32_t fpscr;
|
||||
};
|
||||
|
||||
private:
|
||||
uint32_t getRegs(user_regs& myregs, int num);
|
||||
uint64_t getFpRegs(vfp_regs &myfpregs, int num);
|
||||
|
||||
user_regs regs;
|
||||
user_regs oldregs;
|
||||
|
||||
vfp_regs fpregs;
|
||||
vfp_regs oldfpregs;
|
||||
|
||||
bool regDiffSinceUpdate[numregs];
|
||||
bool foundMvn;
|
||||
|
||||
protected:
|
||||
bool update(int pid);
|
||||
|
||||
public:
|
||||
ARMTraceChild();
|
||||
bool sendState(int socket);
|
||||
|
||||
int64_t getRegVal(int num);
|
||||
int64_t getOldRegVal(int num);
|
||||
|
||||
bool step();
|
||||
|
||||
uint64_t
|
||||
getPC()
|
||||
{
|
||||
return getRegVal(PC);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
getSP()
|
||||
{
|
||||
return getRegVal(SP);
|
||||
}
|
||||
|
||||
std::ostream & outputStartState(std::ostream & os);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
111
simulators/gem5/util/statetrace/arch/i686/tracechild.cc
Normal file
111
simulators/gem5/util/statetrace/arch/i686/tracechild.cc
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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
|
||||
* OWNER 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.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <iostream>
|
||||
|
||||
#include "arch/i686/tracechild.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int64_t
|
||||
I686TraceChild::getRegs(user_regs_struct & myregs, int num)
|
||||
{
|
||||
assert(num < numregs && num >= 0);
|
||||
switch (num) {
|
||||
//GPRs
|
||||
case EAX: return myregs.eax;
|
||||
case EBX: return myregs.ebx;
|
||||
case ECX: return myregs.ecx;
|
||||
case EDX: return myregs.edx;
|
||||
//Index registers
|
||||
case ESI: return myregs.esi;
|
||||
case EDI: return myregs.edi;
|
||||
//Base pointer and stack pointer
|
||||
case EBP: return myregs.ebp;
|
||||
case ESP: return myregs.esp;
|
||||
//Segmentation registers
|
||||
case CS: return myregs.xcs;
|
||||
case DS: return myregs.xds;
|
||||
case ES: return myregs.xes;
|
||||
case FS: return myregs.xfs;
|
||||
case GS: return myregs.xgs;
|
||||
case SS: return myregs.xss;
|
||||
//PC
|
||||
case EIP: return myregs.eip;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
I686TraceChild::update(int pid)
|
||||
{
|
||||
oldregs = regs;
|
||||
if (ptrace(PTRACE_GETREGS, pid, 0, ®s) != 0)
|
||||
return false;
|
||||
for (unsigned int x = 0; x < numregs; x++) {
|
||||
regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
|
||||
}
|
||||
}
|
||||
|
||||
I686TraceChild::I686TraceChild()
|
||||
{
|
||||
for (unsigned int x = 0; x < numregs; x++)
|
||||
regDiffSinceUpdate[x] = false;
|
||||
}
|
||||
|
||||
int64_t
|
||||
I686TraceChild::getRegVal(int num)
|
||||
{
|
||||
return getRegs(regs, num);
|
||||
}
|
||||
|
||||
int64_t
|
||||
I686TraceChild::getOldRegVal(int num)
|
||||
{
|
||||
return getRegs(oldregs, num);
|
||||
}
|
||||
|
||||
bool
|
||||
I686TraceChild::sendState(int socket)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TraceChild *
|
||||
genTraceChild()
|
||||
{
|
||||
return new I686TraceChild;
|
||||
}
|
||||
87
simulators/gem5/util/statetrace/arch/i686/tracechild.hh
Normal file
87
simulators/gem5/util/statetrace/arch/i686/tracechild.hh
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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
|
||||
* OWNER 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.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#ifndef REGSTATE_I686_HH
|
||||
#define REGSTATE_I686_HH
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include "base/tracechild.hh"
|
||||
|
||||
class I686TraceChild : public TraceChild
|
||||
{
|
||||
public:
|
||||
enum RegNum
|
||||
{
|
||||
//GPRs
|
||||
EAX, EBX, ECX, EDX,
|
||||
//Index registers
|
||||
ESI, EDI,
|
||||
//Base pointer and stack pointer
|
||||
EBP, ESP,
|
||||
//Segmentation registers
|
||||
CS, DS, ES, FS, GS, SS,
|
||||
//PC
|
||||
EIP,
|
||||
numregs
|
||||
};
|
||||
private:
|
||||
int64_t getRegs(user_regs_struct & myregs, int num);
|
||||
user_regs_struct regs;
|
||||
user_regs_struct oldregs;
|
||||
bool regDiffSinceUpdate[numregs];
|
||||
|
||||
protected:
|
||||
bool update(int pid);
|
||||
|
||||
public:
|
||||
|
||||
I686TraceChild();
|
||||
|
||||
int64_t getRegVal(int num);
|
||||
int64_t getOldRegVal(int num);
|
||||
uint64_t getPC() {return getRegVal(EIP);}
|
||||
uint64_t getSP() {return getRegVal(ESP);}
|
||||
bool sendState(int socket);
|
||||
std::ostream &
|
||||
outputStartState(std::ostream & output)
|
||||
{
|
||||
output << "Printing i686 initial state not yet implemented"
|
||||
<< std::endl;
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
473
simulators/gem5/util/statetrace/arch/sparc/tracechild.cc
Normal file
473
simulators/gem5/util/statetrace/arch/sparc/tracechild.cc
Normal file
@ -0,0 +1,473 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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
|
||||
* OWNER 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.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <iostream>
|
||||
|
||||
#include "arch/sparc/tracechild.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool
|
||||
SparcTraceChild::sendState(int socket)
|
||||
{
|
||||
uint64_t regVal = 0;
|
||||
for (int x = 0; x <= I7; x++) {
|
||||
regVal = getRegVal(x);
|
||||
if (write(socket, ®Val, sizeof(regVal)) == -1) {
|
||||
cerr << "Write failed! " << strerror(errno) << endl;
|
||||
tracing = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
regVal = getRegVal(PC);
|
||||
if (write(socket, ®Val, sizeof(regVal)) == -1) {
|
||||
cerr << "Write failed! " << strerror(errno) << endl;
|
||||
tracing = false;
|
||||
return false;
|
||||
}
|
||||
regVal = getRegVal(NPC);
|
||||
if (write(socket, ®Val, sizeof(regVal)) == -1) {
|
||||
cerr << "Write failed! " << strerror(errno) << endl;
|
||||
tracing = false;
|
||||
return false;
|
||||
}
|
||||
regVal = getRegVal(CCR);
|
||||
if (write(socket, ®Val, sizeof(regVal)) == -1) {
|
||||
cerr << "Write failed! " << strerror(errno) << endl;
|
||||
tracing = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t
|
||||
getRegs(regs & myregs, fpu & myfpu, uint64_t * locals,
|
||||
uint64_t * inputs, int num)
|
||||
{
|
||||
assert(num < SparcTraceChild::numregs && num >= 0);
|
||||
switch (num) {
|
||||
//Global registers
|
||||
case SparcTraceChild::G0: return 0;
|
||||
case SparcTraceChild::G1: return myregs.r_g1;
|
||||
case SparcTraceChild::G2: return myregs.r_g2;
|
||||
case SparcTraceChild::G3: return myregs.r_g3;
|
||||
case SparcTraceChild::G4: return myregs.r_g4;
|
||||
case SparcTraceChild::G5: return myregs.r_g5;
|
||||
case SparcTraceChild::G6: return myregs.r_g6;
|
||||
case SparcTraceChild::G7: return myregs.r_g7;
|
||||
//Output registers
|
||||
case SparcTraceChild::O0: return myregs.r_o0;
|
||||
case SparcTraceChild::O1: return myregs.r_o1;
|
||||
case SparcTraceChild::O2: return myregs.r_o2;
|
||||
case SparcTraceChild::O3: return myregs.r_o3;
|
||||
case SparcTraceChild::O4: return myregs.r_o4;
|
||||
case SparcTraceChild::O5: return myregs.r_o5;
|
||||
case SparcTraceChild::O6: return myregs.r_o6;
|
||||
case SparcTraceChild::O7: return myregs.r_o7;
|
||||
//Local registers
|
||||
case SparcTraceChild::L0: return locals[0];
|
||||
case SparcTraceChild::L1: return locals[1];
|
||||
case SparcTraceChild::L2: return locals[2];
|
||||
case SparcTraceChild::L3: return locals[3];
|
||||
case SparcTraceChild::L4: return locals[4];
|
||||
case SparcTraceChild::L5: return locals[5];
|
||||
case SparcTraceChild::L6: return locals[6];
|
||||
case SparcTraceChild::L7: return locals[7];
|
||||
//Input registers
|
||||
case SparcTraceChild::I0: return inputs[0];
|
||||
case SparcTraceChild::I1: return inputs[1];
|
||||
case SparcTraceChild::I2: return inputs[2];
|
||||
case SparcTraceChild::I3: return inputs[3];
|
||||
case SparcTraceChild::I4: return inputs[4];
|
||||
case SparcTraceChild::I5: return inputs[5];
|
||||
case SparcTraceChild::I6: return inputs[6];
|
||||
case SparcTraceChild::I7: return inputs[7];
|
||||
//Floating point
|
||||
case SparcTraceChild::F0: return myfpu.f_fpstatus.fpu_fr[0];
|
||||
case SparcTraceChild::F2: return myfpu.f_fpstatus.fpu_fr[1];
|
||||
case SparcTraceChild::F4: return myfpu.f_fpstatus.fpu_fr[2];
|
||||
case SparcTraceChild::F6: return myfpu.f_fpstatus.fpu_fr[3];
|
||||
case SparcTraceChild::F8: return myfpu.f_fpstatus.fpu_fr[4];
|
||||
case SparcTraceChild::F10: return myfpu.f_fpstatus.fpu_fr[5];
|
||||
case SparcTraceChild::F12: return myfpu.f_fpstatus.fpu_fr[6];
|
||||
case SparcTraceChild::F14: return myfpu.f_fpstatus.fpu_fr[7];
|
||||
case SparcTraceChild::F16: return myfpu.f_fpstatus.fpu_fr[8];
|
||||
case SparcTraceChild::F18: return myfpu.f_fpstatus.fpu_fr[9];
|
||||
case SparcTraceChild::F20: return myfpu.f_fpstatus.fpu_fr[10];
|
||||
case SparcTraceChild::F22: return myfpu.f_fpstatus.fpu_fr[11];
|
||||
case SparcTraceChild::F24: return myfpu.f_fpstatus.fpu_fr[12];
|
||||
case SparcTraceChild::F26: return myfpu.f_fpstatus.fpu_fr[13];
|
||||
case SparcTraceChild::F28: return myfpu.f_fpstatus.fpu_fr[14];
|
||||
case SparcTraceChild::F30: return myfpu.f_fpstatus.fpu_fr[15];
|
||||
case SparcTraceChild::F32: return myfpu.f_fpstatus.fpu_fr[16];
|
||||
case SparcTraceChild::F34: return myfpu.f_fpstatus.fpu_fr[17];
|
||||
case SparcTraceChild::F36: return myfpu.f_fpstatus.fpu_fr[18];
|
||||
case SparcTraceChild::F38: return myfpu.f_fpstatus.fpu_fr[19];
|
||||
case SparcTraceChild::F40: return myfpu.f_fpstatus.fpu_fr[20];
|
||||
case SparcTraceChild::F42: return myfpu.f_fpstatus.fpu_fr[21];
|
||||
case SparcTraceChild::F44: return myfpu.f_fpstatus.fpu_fr[22];
|
||||
case SparcTraceChild::F46: return myfpu.f_fpstatus.fpu_fr[23];
|
||||
case SparcTraceChild::F48: return myfpu.f_fpstatus.fpu_fr[24];
|
||||
case SparcTraceChild::F50: return myfpu.f_fpstatus.fpu_fr[25];
|
||||
case SparcTraceChild::F52: return myfpu.f_fpstatus.fpu_fr[26];
|
||||
case SparcTraceChild::F54: return myfpu.f_fpstatus.fpu_fr[27];
|
||||
case SparcTraceChild::F56: return myfpu.f_fpstatus.fpu_fr[28];
|
||||
case SparcTraceChild::F58: return myfpu.f_fpstatus.fpu_fr[29];
|
||||
case SparcTraceChild::F60: return myfpu.f_fpstatus.fpu_fr[30];
|
||||
case SparcTraceChild::F62: return myfpu.f_fpstatus.fpu_fr[31];
|
||||
//Miscelaneous
|
||||
case SparcTraceChild::FSR: return myfpu.f_fpstatus.Fpu_fsr;
|
||||
case SparcTraceChild::FPRS: return myregs.r_fprs;
|
||||
case SparcTraceChild::PC: return myregs.r_tpc;
|
||||
case SparcTraceChild::NPC: return myregs.r_tnpc;
|
||||
case SparcTraceChild::Y: return myregs.r_y;
|
||||
case SparcTraceChild::CWP:
|
||||
return (myregs.r_tstate >> 0) & ((1 << 5) - 1);
|
||||
case SparcTraceChild::PSTATE:
|
||||
return (myregs.r_tstate >> 8) & ((1 << 13) - 1);
|
||||
case SparcTraceChild::ASI:
|
||||
return (myregs.r_tstate >> 24) & ((1 << 8) - 1);
|
||||
case SparcTraceChild::CCR:
|
||||
return (myregs.r_tstate >> 32) & ((1 << 8) - 1);
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
SparcTraceChild::update(int pid)
|
||||
{
|
||||
memcpy(&oldregs, &theregs, sizeof(regs));
|
||||
memcpy(&oldfpregs, &thefpregs, sizeof(fpu));
|
||||
memcpy(oldLocals, locals, 8 * sizeof(uint64_t));
|
||||
memcpy(oldInputs, inputs, 8 * sizeof(uint64_t));
|
||||
if (ptrace(PTRACE_GETREGS, pid, &theregs, 0) != 0) {
|
||||
cerr << "Update failed" << endl;
|
||||
return false;
|
||||
}
|
||||
uint64_t stackPointer = getSP();
|
||||
uint64_t stackBias = 2047;
|
||||
bool v9 = stackPointer % 2;
|
||||
for (unsigned int x = 0; x < 8; x++) {
|
||||
uint64_t localAddr = stackPointer +
|
||||
(v9 ? (stackBias + x * 8) : (x * 4));
|
||||
locals[x] = ptrace(PTRACE_PEEKTEXT, pid, localAddr, 0);
|
||||
if (!v9) locals[x] >>= 32;
|
||||
uint64_t inputAddr = stackPointer +
|
||||
(v9 ? (stackBias + x * 8 + (8 * 8)) : (x * 4 + 8 * 4));
|
||||
inputs[x] = ptrace(PTRACE_PEEKTEXT, pid, inputAddr, 0);
|
||||
if (!v9) inputs[x] >>= 32;
|
||||
}
|
||||
if (ptrace(PTRACE_GETFPREGS, pid, &thefpregs, 0) != 0)
|
||||
return false;
|
||||
for (unsigned int x = 0; x < numregs; x++)
|
||||
regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
|
||||
return true;
|
||||
}
|
||||
|
||||
SparcTraceChild::SparcTraceChild()
|
||||
{
|
||||
for (unsigned int x = 0; x < numregs; x++)
|
||||
regDiffSinceUpdate[x] = false;
|
||||
}
|
||||
|
||||
int
|
||||
SparcTraceChild::getTargets(uint32_t inst, uint64_t pc, uint64_t npc,
|
||||
uint64_t &target1, uint64_t &target2)
|
||||
{
|
||||
//We can identify the instruction categories we care about using the top
|
||||
//10 bits of the instruction, excluding the annul bit in the 3rd most
|
||||
//significant bit position and the condition field. We'll call these
|
||||
//bits the "sig" for signature.
|
||||
uint32_t sig = (inst >> 22) & 0x307;
|
||||
uint32_t cond = (inst >> 25) & 0xf;
|
||||
bool annul = (inst & (1 << 29));
|
||||
|
||||
//Check if it's a ba...
|
||||
bool ba = (cond == 0x8) &&
|
||||
(sig == 0x1 || sig == 0x2 || sig == 0x5 || sig == 0x6);
|
||||
//or a bn...
|
||||
bool bn = (cond == 0x0) &&
|
||||
(sig == 0x1 || sig == 0x2 || sig == 0x5 || sig == 0x6);
|
||||
//or a bcc
|
||||
bool bcc = (cond & 0x7) &&
|
||||
(sig == 0x1 || sig == 0x2 || sig == 0x3 || sig == 0x5 || sig == 0x6);
|
||||
|
||||
if (annul) {
|
||||
if (bcc) {
|
||||
target1 = npc;
|
||||
target2 = npc + 4;
|
||||
return 2;
|
||||
} else if(ba) {
|
||||
//This branches immediately to the effective address of the branch
|
||||
//which we'll have to calculate.
|
||||
uint64_t disp = 0;
|
||||
int64_t extender = 0;
|
||||
//Figure out how big the displacement field is, and grab the bits
|
||||
if (sig == 0x1 || sig == 0x5) {
|
||||
disp = inst & ((1 << 19) - 1);
|
||||
extender = 1 << 18;
|
||||
} else {
|
||||
disp = inst & ((1 << 22) - 1);
|
||||
extender = 1 << 21;
|
||||
}
|
||||
//This does sign extension, believe it or not.
|
||||
disp = (disp ^ extender) - extender;
|
||||
//Multiply the displacement by 4. I'm assuming the compiler is
|
||||
//smart enough to turn this into a shift.
|
||||
disp *= 4;
|
||||
target1 = pc + disp;
|
||||
} else if(bn)
|
||||
target1 = npc + 4;
|
||||
else
|
||||
target1 = npc;
|
||||
return 1;
|
||||
} else {
|
||||
target1 = npc;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
SparcTraceChild::step()
|
||||
{
|
||||
//Increment the count of the number of instructions executed
|
||||
instructions++;
|
||||
//Two important considerations are that the address of the instruction
|
||||
//being breakpointed should be word (64bit) aligned, and that both the
|
||||
//next instruction and the instruction after that need to be breakpointed
|
||||
//so that annulled branches will still stop as well.
|
||||
|
||||
/*
|
||||
* Useful constants
|
||||
*/
|
||||
const static uint64_t breakInst = 0x91d02001;
|
||||
const static uint64_t lowBreakInst = breakInst;
|
||||
const static uint64_t highBreakInst = breakInst << 32;
|
||||
const static uint64_t breakWord = breakInst | (breakInst << 32);
|
||||
const static uint64_t lowMask = 0xFFFFFFFFULL;
|
||||
const static uint64_t highMask = lowMask << 32;
|
||||
|
||||
/*
|
||||
* storage for the original contents of the child process's memory
|
||||
*/
|
||||
uint64_t originalInst, originalAnnulInst;
|
||||
|
||||
/*
|
||||
* Get information about where the process is and is headed next.
|
||||
*/
|
||||
uint64_t currentPC = getRegVal(PC);
|
||||
bool unalignedPC = currentPC & 7;
|
||||
uint64_t alignedPC = currentPC & (~7);
|
||||
uint64_t nextPC = getRegVal(NPC);
|
||||
bool unalignedNPC = nextPC & 7;
|
||||
uint64_t alignedNPC = nextPC & (~7);
|
||||
|
||||
//Get the current instruction
|
||||
uint64_t curInst = ptrace(PTRACE_PEEKTEXT, pid, alignedPC);
|
||||
curInst = unalignedPC ? (curInst & 0xffffffffULL) : (curInst >> 32);
|
||||
|
||||
uint64_t bp1, bp2;
|
||||
int numTargets = getTargets(curInst, currentPC, nextPC, bp1, bp2);
|
||||
assert(numTargets == 1 || numTargets == 2);
|
||||
|
||||
bool unalignedBp1 = bp1 & 7;
|
||||
uint64_t alignedBp1 = bp1 & (~7);
|
||||
bool unalignedBp2 = bp2 & 7;
|
||||
uint64_t alignedBp2 = bp2 & (~7);
|
||||
uint64_t origBp1, origBp2;
|
||||
|
||||
/*
|
||||
* Set the first breakpoint
|
||||
*/
|
||||
origBp1 = ptrace(PTRACE_PEEKTEXT, pid, alignedBp1, 0);
|
||||
uint64_t newBp1 = origBp1;
|
||||
newBp1 &= unalignedBp1 ? highMask : lowMask;
|
||||
newBp1 |= unalignedBp1 ? lowBreakInst : highBreakInst;
|
||||
if (ptrace(PTRACE_POKETEXT, pid, alignedBp1, newBp1) != 0)
|
||||
cerr << "Poke failed" << endl;
|
||||
/*
|
||||
* Set the second breakpoint if necessary
|
||||
*/
|
||||
if (numTargets == 2) {
|
||||
origBp2 = ptrace(PTRACE_PEEKTEXT, pid, alignedBp2, 0);
|
||||
uint64_t newBp2 = origBp2;
|
||||
newBp2 &= unalignedBp2 ? highMask : lowMask;
|
||||
newBp2 |= unalignedBp2 ? lowBreakInst : highBreakInst;
|
||||
if (ptrace(PTRACE_POKETEXT, pid, alignedBp2, newBp2) != 0)
|
||||
cerr << "Poke failed" << endl;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restart the child process
|
||||
*/
|
||||
//Note that the "addr" parameter is supposed to be ignored, but in at
|
||||
//least one version of the kernel, it must be 1 or it will set what
|
||||
//pc to continue from
|
||||
if (ptrace(PTRACE_CONT, pid, 1, 0) != 0)
|
||||
cerr << "Cont failed" << endl;
|
||||
doWait();
|
||||
|
||||
/*
|
||||
* Update our record of the child's state
|
||||
*/
|
||||
update(pid);
|
||||
|
||||
/*
|
||||
* Put back the original contents of the childs address space in the
|
||||
* reverse order.
|
||||
*/
|
||||
if (numTargets == 2) {
|
||||
if (ptrace(PTRACE_POKETEXT, pid, alignedBp2, origBp2) != 0)
|
||||
cerr << "Poke failed" << endl;
|
||||
}
|
||||
if (ptrace(PTRACE_POKETEXT, pid, alignedBp1, origBp1) != 0)
|
||||
cerr << "Poke failed" << endl;
|
||||
}
|
||||
|
||||
int64_t
|
||||
SparcTraceChild::getRegVal(int num)
|
||||
{
|
||||
return getRegs(theregs, thefpregs, locals, inputs, num);
|
||||
}
|
||||
|
||||
int64_t
|
||||
SparcTraceChild::getOldRegVal(int num)
|
||||
{
|
||||
return getRegs(oldregs, oldfpregs, oldLocals, oldInputs, num);
|
||||
}
|
||||
|
||||
ostream &
|
||||
SparcTraceChild::outputStartState(ostream & os)
|
||||
{
|
||||
bool v8 = false;
|
||||
uint64_t sp = getSP();
|
||||
if (sp % 2) {
|
||||
os << "Detected a 64 bit executable.\n";
|
||||
v8 = false;
|
||||
} else {
|
||||
os << "Detected a 32 bit executable.\n";
|
||||
v8 = true;
|
||||
}
|
||||
uint64_t pc = getPC();
|
||||
char obuf[1024];
|
||||
sprintf(obuf, "Initial stack pointer = 0x%016llx\n", sp);
|
||||
os << obuf;
|
||||
sprintf(obuf, "Initial program counter = 0x%016llx\n", pc);
|
||||
os << obuf;
|
||||
if (!v8) {
|
||||
//Take out the stack bias
|
||||
sp += 2047;
|
||||
}
|
||||
//Output the window save area
|
||||
for (unsigned int x = 0; x < 16; x++) {
|
||||
uint64_t regspot = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
if (v8) regspot = regspot >> 32;
|
||||
sprintf(obuf, "0x%016llx: Window save %d = 0x%016llx\n",
|
||||
sp, x+1, regspot);
|
||||
os << obuf;
|
||||
sp += v8 ? 4 : 8;
|
||||
}
|
||||
//Output the argument count
|
||||
uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
if (v8) cargc = cargc >> 32;
|
||||
sprintf(obuf, "0x%016llx: Argc = 0x%016llx\n", sp, cargc);
|
||||
os << obuf;
|
||||
sp += v8 ? 4 : 8;
|
||||
//Output argv pointers
|
||||
int argCount = 0;
|
||||
uint64_t cargv;
|
||||
do {
|
||||
cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
if (v8) cargv = cargv >> 32;
|
||||
sprintf(obuf, "0x%016llx: argv[%d] = 0x%016llx\n",
|
||||
sp, argCount++, cargv);
|
||||
os << obuf;
|
||||
sp += v8 ? 4 : 8;
|
||||
} while(cargv);
|
||||
//Output the envp pointers
|
||||
int envCount = 0;
|
||||
uint64_t cenvp;
|
||||
do {
|
||||
cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
if (v8) cenvp = cenvp >> 32;
|
||||
sprintf(obuf, "0x%016llx: envp[%d] = 0x%016llx\n",
|
||||
sp, envCount++, cenvp);
|
||||
os << obuf;
|
||||
sp += v8 ? 4 : 8;
|
||||
} while (cenvp);
|
||||
uint64_t auxType, auxVal;
|
||||
do {
|
||||
auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
if (v8) auxType = auxType >> 32;
|
||||
sp += (v8 ? 4 : 8);
|
||||
auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
if (v8) auxVal = auxVal >> 32;
|
||||
sp += (v8 ? 4 : 8);
|
||||
sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n",
|
||||
sp - 8, auxType, auxVal);
|
||||
os << obuf;
|
||||
} while (auxType != 0 || auxVal != 0);
|
||||
//Print out the argument strings, environment strings, and file name.
|
||||
string current;
|
||||
uint64_t buf;
|
||||
uint64_t currentStart = sp;
|
||||
bool clearedInitialPadding = false;
|
||||
do {
|
||||
buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
|
||||
char * cbuf = (char *)&buf;
|
||||
for (int x = 0; x < sizeof(uint32_t); x++) {
|
||||
if (cbuf[x])
|
||||
current += cbuf[x];
|
||||
else {
|
||||
sprintf(obuf, "0x%016llx: \"%s\"\n",
|
||||
currentStart, current.c_str());
|
||||
os << obuf;
|
||||
current = "";
|
||||
currentStart = sp + x + 1;
|
||||
}
|
||||
}
|
||||
sp += (v8 ? 4 : 8);
|
||||
clearedInitialPadding = clearedInitialPadding || buf != 0;
|
||||
} while (!clearedInitialPadding || buf != 0);
|
||||
return os;
|
||||
}
|
||||
|
||||
TraceChild *
|
||||
genTraceChild()
|
||||
{
|
||||
return new SparcTraceChild;
|
||||
}
|
||||
|
||||
115
simulators/gem5/util/statetrace/arch/sparc/tracechild.hh
Normal file
115
simulators/gem5/util/statetrace/arch/sparc/tracechild.hh
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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
|
||||
* OWNER 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.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#ifndef TRACECHILD_SPARC_HH
|
||||
#define TRACECHILD_SPARC_HH
|
||||
|
||||
#include <asm-sparc64/reg.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
#include "base/tracechild.hh"
|
||||
|
||||
struct regs;
|
||||
|
||||
class SparcTraceChild : public TraceChild
|
||||
{
|
||||
public:
|
||||
enum RegNum
|
||||
{
|
||||
//Global registers
|
||||
G0, G1, G2, G3, G4, G5, G6, G7,
|
||||
//Output registers
|
||||
O0, O1, O2, O3, O4, O5, O6, O7,
|
||||
//Local registers
|
||||
L0, L1, L2, L3, L4, L5, L6, L7,
|
||||
//Input registers
|
||||
I0, I1, I2, I3, I4, I5, I6, I7,
|
||||
//Floating point
|
||||
F0, F2, F4, F6, F8, F10, F12, F14,
|
||||
F16, F18, F20, F22, F24, F26, F28, F30,
|
||||
F32, F34, F36, F38, F40, F42, F44, F46,
|
||||
F48, F50, F52, F54, F56, F58, F60, F62,
|
||||
//Miscelaneous
|
||||
FSR, FPRS, PC, NPC, Y, CWP, PSTATE, ASI, CCR,
|
||||
numregs
|
||||
};
|
||||
private:
|
||||
regs theregs;
|
||||
regs oldregs;
|
||||
fpu thefpregs;
|
||||
fpu oldfpregs;
|
||||
uint64_t locals[8];
|
||||
uint64_t oldLocals[8];
|
||||
uint64_t inputs[8];
|
||||
uint64_t oldInputs[8];
|
||||
bool regDiffSinceUpdate[numregs];
|
||||
|
||||
//This calculates where the pc might go after the current instruction.
|
||||
//while this equals npc for most instructions, it doesn't for all of
|
||||
//them. The return value is the number of actual potential targets.
|
||||
int getTargets(uint32_t inst, uint64_t pc, uint64_t npc,
|
||||
uint64_t &target1, uint64_t &target2);
|
||||
|
||||
protected:
|
||||
bool update(int pid);
|
||||
|
||||
public:
|
||||
SparcTraceChild();
|
||||
|
||||
bool sendState(int socket);
|
||||
|
||||
int64_t getRegVal(int num);
|
||||
|
||||
int64_t getOldRegVal(int num);
|
||||
|
||||
bool step();
|
||||
|
||||
uint64_t
|
||||
getPC()
|
||||
{
|
||||
return getRegVal(PC);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
getSP()
|
||||
{
|
||||
return getRegVal(O6);
|
||||
}
|
||||
|
||||
std::ostream & outputStartState(std::ostream & os);
|
||||
};
|
||||
|
||||
#endif
|
||||
78
simulators/gem5/util/statetrace/base/arch_check.h
Normal file
78
simulators/gem5/util/statetrace/base/arch_check.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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
|
||||
* OWNER 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.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#if defined __STATETRACE_ALPHA__
|
||||
#if !defined __alpha__
|
||||
#error "Alpha toolchain required."
|
||||
#endif
|
||||
#elif defined __STATETRACE_AMD64__
|
||||
#if !defined __amd64__
|
||||
#error "Amd64 toolchain required."
|
||||
#endif
|
||||
#elif defined __STATETRACE_ARM__
|
||||
#if !defined __arm__
|
||||
#error "Arm toolchain required."
|
||||
#endif
|
||||
#elif defined __STATETRACE_HPPA__
|
||||
#if !defined __hppa__
|
||||
#error "Hppa toolchain required."
|
||||
#endif
|
||||
#elif defined __STATETRACE_I686__
|
||||
#if !(defined __i386__ || defined __i486__ || \
|
||||
defined __i586__ || defined __i686__)
|
||||
#error "I686 toolchain required."
|
||||
#endif
|
||||
#elif defined __STATETRACE_IA64__
|
||||
#if !defined __ia64__
|
||||
#error "IA64 toolchain required."
|
||||
#endif
|
||||
#elif defined __STATETRACE_MIPS__
|
||||
#if !defined __mips__
|
||||
#error "Mips toolchain required."
|
||||
#endif
|
||||
#elif defined __STATETRACE_POWERPC__
|
||||
#if !defined __powerpc__
|
||||
#error "PowerPC toolchain required."
|
||||
#endif
|
||||
#elif defined __STATETRACE_SPARC__
|
||||
#if !defined __sparc__
|
||||
#error "Sparc toolchain required."
|
||||
#endif
|
||||
#elif defined __STATETRACE_SH__
|
||||
#if !defined __sh__
|
||||
#error "SuperH toolchain required."
|
||||
#endif
|
||||
#elif defined __STATETRACE__S390__
|
||||
#if !defined __s390__
|
||||
#error "System/390 toolchain required."
|
||||
#endif
|
||||
#else
|
||||
#error "Couldn't determine architecture."
|
||||
#endif
|
||||
47
simulators/gem5/util/statetrace/base/regstate.hh
Normal file
47
simulators/gem5/util/statetrace/base/regstate.hh
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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
|
||||
* OWNER 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.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#ifndef REGSTATE_H
|
||||
#define REGSTATE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
class RegState
|
||||
{
|
||||
protected:
|
||||
virtual bool update(int pid) = 0;
|
||||
public:
|
||||
virtual int64_t getRegVal(int num) = 0;
|
||||
virtual int64_t getOldRegVal(int num) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
156
simulators/gem5/util/statetrace/base/statetrace.cc
Normal file
156
simulators/gem5/util/statetrace/base/statetrace.cc
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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
|
||||
* OWNER 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.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "base/arch_check.h"
|
||||
#include "tracechild.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void
|
||||
printUsage(const char * execName)
|
||||
{
|
||||
cout << execName << " <options> -- <command> <arguments>" << endl;
|
||||
cout << "options:" << endl;
|
||||
cout << " -h print this help" << endl;
|
||||
cout << " --host remote m5 host to connect to" << endl;
|
||||
cout << " -i print initial stack state" << endl;
|
||||
cout << " -nt don't trace execution" << endl;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char * argv[], char * envp[])
|
||||
{
|
||||
TraceChild * child = genTraceChild();
|
||||
string args;
|
||||
int startProgramArgs;
|
||||
|
||||
//Parse the command line arguments
|
||||
bool printInitial = false;
|
||||
bool printTrace = true;
|
||||
string host = "localhost";
|
||||
|
||||
if (argc == 1) {
|
||||
printUsage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
for (int x = 1; x < argc; x++) {
|
||||
if (!strcmp(argv[x], "-h")) {
|
||||
printUsage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(argv[x], "--host")) {
|
||||
x++;
|
||||
if (x >= argc) {
|
||||
cerr << "Incorrect usage.\n" << endl;
|
||||
printUsage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
host = argv[x];
|
||||
} else if (!strcmp(argv[x], "-i")) {
|
||||
printInitial = true;
|
||||
} else if (!strcmp(argv[x], "-nt")) {
|
||||
printTrace = false;
|
||||
} else if (!strcmp(argv[x], "--")) {
|
||||
x++;
|
||||
if (x >= argc) {
|
||||
cerr << "Incorrect usage.\n" << endl;
|
||||
printUsage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
startProgramArgs = x;
|
||||
break;
|
||||
} else {
|
||||
cerr << "Incorrect usage.\n" << endl;
|
||||
printUsage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!child->startTracing(argv[startProgramArgs],
|
||||
argv + startProgramArgs)) {
|
||||
cerr << "Couldn't start target program" << endl;
|
||||
return 1;
|
||||
}
|
||||
child->step();
|
||||
if (printInitial)
|
||||
child->outputStartState(cout);
|
||||
if (printTrace) {
|
||||
// Connect to m5
|
||||
bool portSet = false;
|
||||
int port;
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
cerr << "Error opening socket! " << strerror(errno) << endl;
|
||||
return 1;
|
||||
}
|
||||
struct hostent *server;
|
||||
server = gethostbyname(host.c_str());
|
||||
if (!server) {
|
||||
cerr << "Couldn't get host ip! " << strerror(errno) << endl;
|
||||
return 1;
|
||||
}
|
||||
struct sockaddr_in serv_addr;
|
||||
bzero((char *)&serv_addr, sizeof(serv_addr));
|
||||
serv_addr.sin_family = AF_INET;
|
||||
bcopy((char *)server->h_addr,
|
||||
(char *)&serv_addr.sin_addr.s_addr,
|
||||
server->h_length);
|
||||
serv_addr.sin_port = htons(8000);
|
||||
if (connect(sock, (sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
|
||||
cerr << "Couldn't connect to server! " << strerror(errno) << endl;
|
||||
return 1;
|
||||
}
|
||||
while (child->isTracing()) {
|
||||
if (!child->sendState(sock))
|
||||
break;
|
||||
child->step();
|
||||
}
|
||||
}
|
||||
if (!child->stopTracing()) {
|
||||
cerr << "Couldn't stop child" << endl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
149
simulators/gem5/util/statetrace/base/tracechild.cc
Normal file
149
simulators/gem5/util/statetrace/base/tracechild.cc
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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
|
||||
* OWNER 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.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#include "tracechild.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool
|
||||
TraceChild::startTracing(const char * pathToFile, char * const argv[])
|
||||
{
|
||||
instructions = 0;
|
||||
pid = fork();
|
||||
if (pid == -1) {
|
||||
cout << "fork failed" << endl;
|
||||
return false;
|
||||
} else if (pid == 0) {
|
||||
//We're the child. Get things ready and then exec the program to trace.
|
||||
//Let our parent trace us
|
||||
if (ptrace(PTRACE_TRACEME, 0, 0, 0) == -1) {
|
||||
cout << "Failure calling TRACEME\n" << strerror(errno) << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
//Set up an empty environment for the child... We would want to
|
||||
//specify this somehow at some point
|
||||
char * env[] = {NULL};
|
||||
|
||||
//Start the program to trace
|
||||
execve(pathToFile, argv, env);
|
||||
|
||||
//We should never get here, so this is an error!
|
||||
cout << "Exec failed\n" << strerror(errno) << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
//From this point forward, we know we're in the parent process.
|
||||
if (!doWait()) {
|
||||
cout << "Didn't wait successfully" << endl;
|
||||
return false;
|
||||
}
|
||||
tracing = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TraceChild::stopTracing()
|
||||
{
|
||||
if (ptrace(PTRACE_KILL, pid, 0, 0) != 0)
|
||||
return false;
|
||||
tracing = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TraceChild::step()
|
||||
{
|
||||
ptraceSingleStep();
|
||||
}
|
||||
|
||||
bool
|
||||
TraceChild::ptraceSingleStep()
|
||||
{
|
||||
if (!tracing) {
|
||||
cout << "Not tracing!" << endl;
|
||||
return false;
|
||||
}
|
||||
if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0) != 0) {
|
||||
switch (errno) {
|
||||
case EBUSY: cout << "EBUSY" << endl; break;
|
||||
case EFAULT: cout << "EFAULT" << endl; break;
|
||||
case EIO: cout << "EIO" << endl; break;
|
||||
case EPERM: cout << "EPERM" << endl; break;
|
||||
case ESRCH: cout << "ESRCH" << endl; break;
|
||||
default: cout << "Unknown error" << endl; break;
|
||||
}
|
||||
cout << "Not able to single step!" << endl;
|
||||
tracing == false;
|
||||
return false;
|
||||
}
|
||||
doWait();
|
||||
update(pid);
|
||||
}
|
||||
|
||||
bool
|
||||
TraceChild::doWait()
|
||||
{
|
||||
int wait_val;
|
||||
wait(&wait_val);
|
||||
if (WIFEXITED(wait_val)) {
|
||||
cerr << "Program exited! Exit status is "
|
||||
<< WEXITSTATUS(wait_val) << endl;
|
||||
cerr << "Executed " << instructions
|
||||
<< " instructions." << endl;
|
||||
tracing = false;
|
||||
return false;
|
||||
}
|
||||
if (WIFSIGNALED(wait_val)) {
|
||||
if (WTERMSIG(wait_val))
|
||||
cerr << "Program terminated by signal "
|
||||
<< WTERMSIG(wait_val) << endl;
|
||||
if (WCOREDUMP(wait_val))
|
||||
cerr << "Program core dumped!" << endl;
|
||||
tracing = false;
|
||||
cerr << "Executed " << instructions
|
||||
<< " instructions." << endl;
|
||||
return false;
|
||||
}
|
||||
if (WIFSTOPPED(wait_val) && WSTOPSIG(wait_val) != SIGTRAP) {
|
||||
cerr << "Program stopped by signal " << WSTOPSIG(wait_val) << endl;
|
||||
tracing = false;
|
||||
cerr << "Executed " << instructions << " instructions." << endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
62
simulators/gem5/util/statetrace/base/tracechild.hh
Normal file
62
simulators/gem5/util/statetrace/base/tracechild.hh
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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
|
||||
* OWNER 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.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#ifndef TRACECHILD_HH
|
||||
#define TRACECHILD_HH
|
||||
|
||||
#include "base/regstate.hh"
|
||||
|
||||
class TraceChild : public RegState
|
||||
{
|
||||
protected:
|
||||
int pid;
|
||||
uint64_t instructions;
|
||||
bool tracing;
|
||||
public:
|
||||
TraceChild() : tracing(false), instructions(0)
|
||||
{;}
|
||||
virtual bool sendState(int socket) = 0;
|
||||
virtual bool startTracing(const char * pathToFile, char * const argv[]);
|
||||
virtual bool stopTracing();
|
||||
virtual bool step();
|
||||
virtual std::ostream & outputStartState(std::ostream & os) = 0;
|
||||
bool
|
||||
isTracing()
|
||||
{
|
||||
return tracing;
|
||||
}
|
||||
protected:
|
||||
bool ptraceSingleStep();
|
||||
bool doWait();
|
||||
};
|
||||
|
||||
TraceChild * genTraceChild();
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user