Statetrace: Accomodate cross compiling statetrace with scons.
authorGabe Black <gblack@eecs.umich.edu>
Thu, 3 Mar 2011 06:53:11 +0000 (22:53 -0800)
committerGabe Black <gblack@eecs.umich.edu>
Thu, 3 Mar 2011 06:53:11 +0000 (22:53 -0800)
--HG--
rename : util/statetrace/arch/tracechild_amd64.cc => util/statetrace/arch/amd64/tracechild.cc
rename : util/statetrace/arch/tracechild_amd64.hh => util/statetrace/arch/amd64/tracechild.hh
rename : util/statetrace/arch/tracechild_arm.cc => util/statetrace/arch/arm/tracechild.cc
rename : util/statetrace/arch/tracechild_arm.hh => util/statetrace/arch/arm/tracechild.hh
rename : util/statetrace/arch/tracechild_i386.cc => util/statetrace/arch/i386/tracechild.cc
rename : util/statetrace/arch/tracechild_i386.hh => util/statetrace/arch/i386/tracechild.hh
rename : util/statetrace/arch/tracechild_sparc.cc => util/statetrace/arch/sparc/tracechild.cc
rename : util/statetrace/arch/tracechild_sparc.hh => util/statetrace/arch/sparc/tracechild.hh
rename : util/statetrace/tracechild_arch.cc => util/statetrace/base/arch_check.h
rename : util/statetrace/regstate.hh => util/statetrace/base/regstate.hh
rename : util/statetrace/statetrace.cc => util/statetrace/base/statetrace.cc
rename : util/statetrace/tracechild.cc => util/statetrace/base/tracechild.cc
rename : util/statetrace/tracechild.hh => util/statetrace/base/tracechild.hh

28 files changed:
util/statetrace/SConscript [new file with mode: 0644]
util/statetrace/SConstruct
util/statetrace/arch/amd64/tracechild.cc [new file with mode: 0644]
util/statetrace/arch/amd64/tracechild.hh [new file with mode: 0644]
util/statetrace/arch/arm/tracechild.cc [new file with mode: 0644]
util/statetrace/arch/arm/tracechild.hh [new file with mode: 0644]
util/statetrace/arch/i386/tracechild.cc [new file with mode: 0644]
util/statetrace/arch/i386/tracechild.hh [new file with mode: 0644]
util/statetrace/arch/sparc/tracechild.cc [new file with mode: 0644]
util/statetrace/arch/sparc/tracechild.hh [new file with mode: 0644]
util/statetrace/arch/tracechild_amd64.cc [deleted file]
util/statetrace/arch/tracechild_amd64.hh [deleted file]
util/statetrace/arch/tracechild_arm.cc [deleted file]
util/statetrace/arch/tracechild_arm.hh [deleted file]
util/statetrace/arch/tracechild_i386.cc [deleted file]
util/statetrace/arch/tracechild_i386.hh [deleted file]
util/statetrace/arch/tracechild_sparc.cc [deleted file]
util/statetrace/arch/tracechild_sparc.hh [deleted file]
util/statetrace/base/arch_check.h [new file with mode: 0644]
util/statetrace/base/regstate.hh [new file with mode: 0644]
util/statetrace/base/statetrace.cc [new file with mode: 0644]
util/statetrace/base/tracechild.cc [new file with mode: 0644]
util/statetrace/base/tracechild.hh [new file with mode: 0644]
util/statetrace/regstate.hh [deleted file]
util/statetrace/statetrace.cc [deleted file]
util/statetrace/tracechild.cc [deleted file]
util/statetrace/tracechild.hh [deleted file]
util/statetrace/tracechild_arch.cc [deleted file]

diff --git a/util/statetrace/SConscript b/util/statetrace/SConscript
new file mode 100644 (file)
index 0000000..7099b0a
--- /dev/null
@@ -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)
index de0eade6a8c94ae446aeda0770124aa7f5bd0177..2e93162d8770a2b82e0061a6a5fc78bf0359f17d 100644 (file)
 #
 # Authors: Gabe Black
 
-sources = ['statetrace.cc', 'tracechild.cc', 'tracechild_arch.cc']
-cxx_flags = "-O3 -ggdb -I ./ -I ./arch"
-objects = [Object(source, CXXFLAGS=cxx_flags) for source in sources]
-Program('statetrace', objects)
+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', 'i386', '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))
diff --git a/util/statetrace/arch/amd64/tracechild.cc b/util/statetrace/arch/amd64/tracechild.cc
new file mode 100644 (file)
index 0000000..5d3b660
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * 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 <iostream>
+#include <iomanip>
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <stdint.h>
+#include <string.h>
+
+#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, &regVal64, sizeof(regVal64)) == -1) {
+            cerr << "Write failed! " << strerror(errno) << endl;
+            tracing = false;
+            return false;
+        }
+    }
+    regVal64 = getRegVal(RIP);
+    if (write(socket, &regVal64, 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, &regVal32, 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, &regVal32, 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, &regs) != 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;
+}
diff --git a/util/statetrace/arch/amd64/tracechild.hh b/util/statetrace/arch/amd64/tracechild.hh
new file mode 100644 (file)
index 0000000..6f28bc0
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * 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/user.h>
+#include <sys/types.h>
+#include <sys/ptrace.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
diff --git a/util/statetrace/arch/arm/tracechild.cc b/util/statetrace/arch/arm/tracechild.cc
new file mode 100644 (file)
index 0000000..97b8d06
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * 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 <iostream>
+#include <errno.h>
+#include <stdint.h>
+#include <cstring>
+#include <cstdio>
+
+#include "arch/arm/tracechild.hh"
+
+using namespace std;
+
+ARMTraceChild::ARMTraceChild()
+{
+    foundMvn = false;
+
+    for (int x = 0; x < numregs; x++) {
+        memset(&regs, 0, sizeof(regs));
+        memset(&oldregs, 0, sizeof(regs));
+        regDiffSinceUpdate[x] = false;
+    }
+}
+
+bool
+ARMTraceChild::sendState(int socket)
+{
+    uint32_t regVal = 0;
+    uint32_t message[numregs + 1];
+    int pos = 1;
+    message[0] = 0;
+    for (int x = 0; x < numregs; x++) {
+        if (regDiffSinceUpdate[x]) {
+            message[0] = message[0] | (1 << 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 < numregs && num >= 0);
+    return myregs.uregs[num];
+}
+
+bool
+ARMTraceChild::update(int pid)
+{
+    oldregs = regs;
+    if (ptrace(PTRACE_GETREGS, pid, 0, &regs) != 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)
+{
+    return getRegs(regs, num);
+}
+
+int64_t
+ARMTraceChild::getOldRegVal(int num)
+{
+    return getRegs(oldregs,  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;
+}
+
diff --git a/util/statetrace/arch/arm/tracechild.hh b/util/statetrace/arch/arm/tracechild.hh
new file mode 100644 (file)
index 0000000..f4e8ca6
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * 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 <cassert>
+#include <string>
+#include <sys/user.h>
+#include <sys/ptrace.h>
+#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,
+        numregs
+    };
+  private:
+    uint32_t getRegs(user_regs& myregs, int num);
+    user_regs regs;
+    user_regs oldregs;
+    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
+
diff --git a/util/statetrace/arch/i386/tracechild.cc b/util/statetrace/arch/i386/tracechild.cc
new file mode 100644 (file)
index 0000000..0d86876
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * 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 <iostream>
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <stdint.h>
+
+#include "arch/i386/tracechild.hh"
+
+using namespace std;
+
+int64_t
+I386TraceChild::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.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;
+      //PC
+      case EIP: return myregs.eip;
+      default:
+        assert(0);
+        return 0;
+    }
+}
+
+bool
+I386TraceChild::update(int pid)
+{
+    oldregs = regs;
+    if (ptrace(PTRACE_GETREGS, pid, 0, &regs) != 0)
+        return false;
+    for (unsigned int x = 0; x < numregs; x++) {
+        regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
+    }
+}
+
+I386TraceChild::I386TraceChild()
+{
+    for (unsigned int x = 0; x < numregs; x++)
+        regDiffSinceUpdate[x] = false;
+}
+
+int64_t
+I386TraceChild::getRegVal(int num)
+{
+    return getRegs(regs, num);
+}
+
+int64_t
+I386TraceChild::getOldRegVal(int num)
+{
+    return getRegs(oldregs, num);
+}
+
+TraceChild *
+genTraceChild()
+{
+    return new I386TraceChild;
+}
diff --git a/util/statetrace/arch/i386/tracechild.hh b/util/statetrace/arch/i386/tracechild.hh
new file mode 100644 (file)
index 0000000..3af621e
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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_I386_HH
+#define REGSTATE_I386_HH
+
+#include <linux/user.h>
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <cassert>
+#include <string>
+
+#include "base/tracechild.hh"
+
+class I386TraceChild : 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:
+
+    I386TraceChild();
+
+    int64_t getRegVal(int num);
+    int64_t getOldRegVal(int num);
+    uint64_t getPC() {return getRegVal(EIP);}
+    uint64_t getSP() {return getRegVal(ESP);}
+    std::ostream &
+    outputStartState(std::ostream & output)
+    {
+        output << "Printing i386 initial state not yet implemented"
+               << std::endl;
+        return output;
+    }
+};
+
+#endif
diff --git a/util/statetrace/arch/sparc/tracechild.cc b/util/statetrace/arch/sparc/tracechild.cc
new file mode 100644 (file)
index 0000000..b18739e
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ * 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 <iostream>
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <stdint.h>
+
+#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, &regVal, sizeof(regVal)) == -1) {
+            cerr << "Write failed! " << strerror(errno) << endl;
+            tracing = false;
+            return false;
+        }
+    }
+    regVal = getRegVal(PC);
+    if (write(socket, &regVal, sizeof(regVal)) == -1) {
+        cerr << "Write failed! " << strerror(errno) << endl;
+        tracing = false;
+        return false;
+    }
+    regVal = getRegVal(NPC);
+    if (write(socket, &regVal, sizeof(regVal)) == -1) {
+        cerr << "Write failed! " << strerror(errno) << endl;
+        tracing = false;
+        return false;
+    }
+    regVal = getRegVal(CCR);
+    if (write(socket, &regVal, 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;
+}
+
diff --git a/util/statetrace/arch/sparc/tracechild.hh b/util/statetrace/arch/sparc/tracechild.hh
new file mode 100644 (file)
index 0000000..2767060
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * 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 <cassert>
+#include <ostream>
+#include <stdint.h>
+#include <string>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+
+#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
diff --git a/util/statetrace/arch/tracechild_amd64.cc b/util/statetrace/arch/tracechild_amd64.cc
deleted file mode 100644 (file)
index 780bb75..0000000
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * 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 <iostream>
-#include <iomanip>
-#include <errno.h>
-#include <sys/ptrace.h>
-#include <stdint.h>
-#include <string.h>
-
-#include "tracechild_amd64.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, &regVal64, sizeof(regVal64)) == -1) {
-            cerr << "Write failed! " << strerror(errno) << endl;
-            tracing = false;
-            return false;
-        }
-    }
-    regVal64 = getRegVal(RIP);
-    if (write(socket, &regVal64, 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, &regVal32, 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, &regVal32, 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, &regs) != 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;
-}
diff --git a/util/statetrace/arch/tracechild_amd64.hh b/util/statetrace/arch/tracechild_amd64.hh
deleted file mode 100644 (file)
index 256be57..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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/user.h>
-#include <sys/types.h>
-#include <sys/ptrace.h>
-#include <cassert>
-#include <string>
-
-#include "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
diff --git a/util/statetrace/arch/tracechild_arm.cc b/util/statetrace/arch/tracechild_arm.cc
deleted file mode 100644 (file)
index bd4f4bd..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * 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 <iostream>
-#include <errno.h>
-#include <stdint.h>
-#include <cstring>
-#include <cstdio>
-
-#include "tracechild_arm.hh"
-
-using namespace std;
-
-ARMTraceChild::ARMTraceChild()
-{
-    foundMvn = false;
-
-    for (int x = 0; x < numregs; x++) {
-        memset(&regs, 0, sizeof(regs));
-        memset(&oldregs, 0, sizeof(regs));
-        regDiffSinceUpdate[x] = false;
-    }
-}
-
-bool
-ARMTraceChild::sendState(int socket)
-{
-    uint32_t regVal = 0;
-    uint32_t message[numregs + 1];
-    int pos = 1;
-    message[0] = 0;
-    for (int x = 0; x < numregs; x++) {
-        if (regDiffSinceUpdate[x]) {
-            message[0] = message[0] | (1 << 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 < numregs && num >= 0);
-    return myregs.uregs[num];
-}
-
-bool
-ARMTraceChild::update(int pid)
-{
-    oldregs = regs;
-    if (ptrace(PTRACE_GETREGS, pid, 0, &regs) != 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)
-{
-    return getRegs(regs, num);
-}
-
-int64_t
-ARMTraceChild::getOldRegVal(int num)
-{
-    return getRegs(oldregs,  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;
-}
-
diff --git a/util/statetrace/arch/tracechild_arm.hh b/util/statetrace/arch/tracechild_arm.hh
deleted file mode 100644 (file)
index 0379885..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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 <cassert>
-#include <string>
-#include <sys/user.h>
-#include <sys/ptrace.h>
-#include "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,
-        numregs
-    };
-  private:
-    uint32_t getRegs(user_regs& myregs, int num);
-    user_regs regs;
-    user_regs oldregs;
-    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
-
diff --git a/util/statetrace/arch/tracechild_i386.cc b/util/statetrace/arch/tracechild_i386.cc
deleted file mode 100644 (file)
index 2cdeb29..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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 <iostream>
-#include <errno.h>
-#include <sys/ptrace.h>
-#include <stdint.h>
-
-#include "tracechild_i386.hh"
-
-using namespace std;
-
-int64_t
-I386TraceChild::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.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;
-      //PC
-      case EIP: return myregs.eip;
-      default:
-        assert(0);
-        return 0;
-    }
-}
-
-bool
-I386TraceChild::update(int pid)
-{
-    oldregs = regs;
-    if (ptrace(PTRACE_GETREGS, pid, 0, &regs) != 0)
-        return false;
-    for (unsigned int x = 0; x < numregs; x++) {
-        regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
-    }
-}
-
-I386TraceChild::I386TraceChild()
-{
-    for (unsigned int x = 0; x < numregs; x++)
-        regDiffSinceUpdate[x] = false;
-}
-
-int64_t
-I386TraceChild::getRegVal(int num)
-{
-    return getRegs(regs, num);
-}
-
-int64_t
-I386TraceChild::getOldRegVal(int num)
-{
-    return getRegs(oldregs, num);
-}
-
-TraceChild *
-genTraceChild()
-{
-    return new I386TraceChild;
-}
diff --git a/util/statetrace/arch/tracechild_i386.hh b/util/statetrace/arch/tracechild_i386.hh
deleted file mode 100644 (file)
index 7f9f749..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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_I386_HH
-#define REGSTATE_I386_HH
-
-#include <linux/user.h>
-#include <sys/types.h>
-#include <sys/ptrace.h>
-#include <cassert>
-#include <string>
-
-#include "tracechild.hh"
-
-class I386TraceChild : 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:
-
-    I386TraceChild();
-
-    int64_t getRegVal(int num);
-    int64_t getOldRegVal(int num);
-    uint64_t getPC() {return getRegVal(EIP);}
-    uint64_t getSP() {return getRegVal(ESP);}
-    std::ostream &
-    outputStartState(std::ostream & output)
-    {
-        output << "Printing i386 initial state not yet implemented"
-               << std::endl;
-        return output;
-    }
-};
-
-#endif
diff --git a/util/statetrace/arch/tracechild_sparc.cc b/util/statetrace/arch/tracechild_sparc.cc
deleted file mode 100644 (file)
index dba8fa5..0000000
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * 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 <iostream>
-#include <errno.h>
-#include <sys/ptrace.h>
-#include <stdint.h>
-
-#include "tracechild_sparc.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, &regVal, sizeof(regVal)) == -1) {
-            cerr << "Write failed! " << strerror(errno) << endl;
-            tracing = false;
-            return false;
-        }
-    }
-    regVal = getRegVal(PC);
-    if (write(socket, &regVal, sizeof(regVal)) == -1) {
-        cerr << "Write failed! " << strerror(errno) << endl;
-        tracing = false;
-        return false;
-    }
-    regVal = getRegVal(NPC);
-    if (write(socket, &regVal, sizeof(regVal)) == -1) {
-        cerr << "Write failed! " << strerror(errno) << endl;
-        tracing = false;
-        return false;
-    }
-    regVal = getRegVal(CCR);
-    if (write(socket, &regVal, 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;
-}
-
diff --git a/util/statetrace/arch/tracechild_sparc.hh b/util/statetrace/arch/tracechild_sparc.hh
deleted file mode 100644 (file)
index e479fce..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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 <cassert>
-#include <ostream>
-#include <stdint.h>
-#include <string>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-
-#include "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
diff --git a/util/statetrace/base/arch_check.h b/util/statetrace/base/arch_check.h
new file mode 100644 (file)
index 0000000..db513a0
--- /dev/null
@@ -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_I386__
+    #if !(defined __i386__ || defined __i486__ || \
+            defined __i586__ || defined __i686)
+        #error "I386 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
diff --git a/util/statetrace/base/regstate.hh b/util/statetrace/base/regstate.hh
new file mode 100644 (file)
index 0000000..bab3485
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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 <string>
+#include <stdint.h>
+
+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
diff --git a/util/statetrace/base/statetrace.cc b/util/statetrace/base/statetrace.cc
new file mode 100644 (file)
index 0000000..c01147b
--- /dev/null
@@ -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 "base/arch_check.h"
+
+#include <cstring>
+#include <errno.h>
+#include <fstream>
+#include <iostream>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string>
+#include <sys/ptrace.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.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 print an instruction trace" << 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;
+}
+
diff --git a/util/statetrace/base/tracechild.cc b/util/statetrace/base/tracechild.cc
new file mode 100644 (file)
index 0000000..b5665ff
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * 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 "tracechild.hh"
+#include <cstring>
+#include <errno.h>
+#include <iostream>
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+
+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;
+}
diff --git a/util/statetrace/base/tracechild.hh b/util/statetrace/base/tracechild.hh
new file mode 100644 (file)
index 0000000..bca04b4
--- /dev/null
@@ -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
diff --git a/util/statetrace/regstate.hh b/util/statetrace/regstate.hh
deleted file mode 100644 (file)
index bab3485..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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 <string>
-#include <stdint.h>
-
-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
diff --git a/util/statetrace/statetrace.cc b/util/statetrace/statetrace.cc
deleted file mode 100644 (file)
index ccc408f..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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 <cstring>
-#include <errno.h>
-#include <fstream>
-#include <iostream>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <stdio.h>
-#include <string>
-#include <sys/ptrace.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.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 print an instruction trace" << 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;
-}
-
diff --git a/util/statetrace/tracechild.cc b/util/statetrace/tracechild.cc
deleted file mode 100644 (file)
index b5665ff..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * 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 "tracechild.hh"
-#include <cstring>
-#include <errno.h>
-#include <iostream>
-#include <sys/ptrace.h>
-#include <sys/wait.h>
-
-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;
-}
diff --git a/util/statetrace/tracechild.hh b/util/statetrace/tracechild.hh
deleted file mode 100644 (file)
index ad7e60e..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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 "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
diff --git a/util/statetrace/tracechild_arch.cc b/util/statetrace/tracechild_arch.cc
deleted file mode 100644 (file)
index 052784d..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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 __alpha__
-    #error "Alpha architecture not implemented"
-#elif defined __amd64__
-    #include "arch/tracechild_amd64.cc"
-#elif defined __arm__
-    #include "arch/tracechild_arm.cc"
-#elif defined __hppa__
-    #error "Hppa architecture not implemented"
-#elif defined __i386__ || defined __i486__ || \
-                defined __i586__ || defined __i686
-    #include "arch/tracechild_i386.cc"
-#elif defined __ia64__
-    #error "IA64 architecture not implemented"
-#elif defined __mips__
-    #error "Mips architecture not implemented"
-#elif defined __powerpc__
-    #error "PowerPC architecture not implemented"
-#elif defined __sparc__
-    #include "arch/tracechild_sparc.cc"
-#elif defined __sh__
-    #include "SuperH architecture not implemented"
-#elif defined __s390__
-    #include "System/390 architecture not implemented"
-#else
-    #error "Couldn't determine architecture"
-#endif