--- /dev/null
+# 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)
#
# 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))
--- /dev/null
+/*
+ * 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, ®Val64, sizeof(regVal64)) == -1) {
+ cerr << "Write failed! " << strerror(errno) << endl;
+ tracing = false;
+ return false;
+ }
+ }
+ regVal64 = getRegVal(RIP);
+ if (write(socket, ®Val64, sizeof(regVal64)) == -1) {
+ cerr << "Write failed! " << strerror(errno) << endl;
+ tracing = false;
+ return false;
+ }
+ for (int x = MMX0_0; x <= MMX7_1; x++) {
+ regVal32 = getRegVal(x);
+ if (write(socket, ®Val32, sizeof(regVal32)) == -1) {
+ cerr << "Write failed! " << strerror(errno) << endl;
+ tracing = false;
+ return false;
+ }
+ }
+ for (int x = XMM0_0; x <= XMM15_3; x++) {
+ regVal32 = getRegVal(x);
+ if (write(socket, ®Val32, sizeof(regVal32)) == -1) {
+ cerr << "Write failed! " << strerror(errno) << endl;
+ tracing = false;
+ return false;
+ }
+ }
+ return true;
+}
+
+int64_t
+AMD64TraceChild::getRegs(user_regs_struct & myregs,
+ user_fpregs_struct & myfpregs, int num)
+{
+ assert(num < numregs && num >= 0);
+ switch (num) {
+ //GPRs
+ case RAX: return myregs.rax;
+ case RBX: return myregs.rbx;
+ case RCX: return myregs.rcx;
+ case RDX: return myregs.rdx;
+ //Index registers
+ case RSI: return myregs.rsi;
+ case RDI: return myregs.rdi;
+ //Base pointer and stack pointer
+ case RBP: return myregs.rbp;
+ case RSP: return myregs.rsp;
+ //New 64 bit mode registers
+ case R8: return myregs.r8;
+ case R9: return myregs.r9;
+ case R10: return myregs.r10;
+ case R11: return myregs.r11;
+ case R12: return myregs.r12;
+ case R13: return myregs.r13;
+ case R14: return myregs.r14;
+ case R15: return myregs.r15;
+ //Segmentation registers
+ case CS: return myregs.cs;
+ case DS: return myregs.ds;
+ case ES: return myregs.es;
+ case FS: return myregs.fs;
+ case GS: return myregs.gs;
+ case SS: return myregs.ss;
+ case FS_BASE: return myregs.fs_base;
+ case GS_BASE: return myregs.gs_base;
+ //PC
+ case RIP: return myregs.rip;
+ //Flags
+ case EFLAGS: return myregs.eflags;
+ //MMX
+ case MMX0_0: return myfpregs.st_space[0];
+ case MMX0_1: return myfpregs.st_space[1];
+ case MMX1_0: return myfpregs.st_space[2];
+ case MMX1_1: return myfpregs.st_space[3];
+ case MMX2_0: return myfpregs.st_space[4];
+ case MMX2_1: return myfpregs.st_space[5];
+ case MMX3_0: return myfpregs.st_space[6];
+ case MMX3_1: return myfpregs.st_space[7];
+ case MMX4_0: return myfpregs.st_space[8];
+ case MMX4_1: return myfpregs.st_space[9];
+ case MMX5_0: return myfpregs.st_space[10];
+ case MMX5_1: return myfpregs.st_space[11];
+ case MMX6_0: return myfpregs.st_space[12];
+ case MMX6_1: return myfpregs.st_space[13];
+ case MMX7_0: return myfpregs.st_space[14];
+ case MMX7_1: return myfpregs.st_space[15];
+ //XMM
+ case XMM0_0: return myfpregs.xmm_space[0];
+ case XMM0_1: return myfpregs.xmm_space[1];
+ case XMM0_2: return myfpregs.xmm_space[2];
+ case XMM0_3: return myfpregs.xmm_space[3];
+ case XMM1_0: return myfpregs.xmm_space[4];
+ case XMM1_1: return myfpregs.xmm_space[5];
+ case XMM1_2: return myfpregs.xmm_space[6];
+ case XMM1_3: return myfpregs.xmm_space[7];
+ case XMM2_0: return myfpregs.xmm_space[8];
+ case XMM2_1: return myfpregs.xmm_space[9];
+ case XMM2_2: return myfpregs.xmm_space[10];
+ case XMM2_3: return myfpregs.xmm_space[11];
+ case XMM3_0: return myfpregs.xmm_space[12];
+ case XMM3_1: return myfpregs.xmm_space[13];
+ case XMM3_2: return myfpregs.xmm_space[14];
+ case XMM3_3: return myfpregs.xmm_space[15];
+ case XMM4_0: return myfpregs.xmm_space[16];
+ case XMM4_1: return myfpregs.xmm_space[17];
+ case XMM4_2: return myfpregs.xmm_space[18];
+ case XMM4_3: return myfpregs.xmm_space[19];
+ case XMM5_0: return myfpregs.xmm_space[20];
+ case XMM5_1: return myfpregs.xmm_space[21];
+ case XMM5_2: return myfpregs.xmm_space[22];
+ case XMM5_3: return myfpregs.xmm_space[23];
+ case XMM6_0: return myfpregs.xmm_space[24];
+ case XMM6_1: return myfpregs.xmm_space[25];
+ case XMM6_2: return myfpregs.xmm_space[26];
+ case XMM6_3: return myfpregs.xmm_space[27];
+ case XMM7_0: return myfpregs.xmm_space[28];
+ case XMM7_1: return myfpregs.xmm_space[29];
+ case XMM7_2: return myfpregs.xmm_space[30];
+ case XMM7_3: return myfpregs.xmm_space[31];
+ case XMM8_0: return myfpregs.xmm_space[32];
+ case XMM8_1: return myfpregs.xmm_space[33];
+ case XMM8_2: return myfpregs.xmm_space[34];
+ case XMM8_3: return myfpregs.xmm_space[35];
+ case XMM9_0: return myfpregs.xmm_space[36];
+ case XMM9_1: return myfpregs.xmm_space[37];
+ case XMM9_2: return myfpregs.xmm_space[38];
+ case XMM9_3: return myfpregs.xmm_space[39];
+ case XMM10_0: return myfpregs.xmm_space[40];
+ case XMM10_1: return myfpregs.xmm_space[41];
+ case XMM10_2: return myfpregs.xmm_space[42];
+ case XMM10_3: return myfpregs.xmm_space[43];
+ case XMM11_0: return myfpregs.xmm_space[44];
+ case XMM11_1: return myfpregs.xmm_space[45];
+ case XMM11_2: return myfpregs.xmm_space[46];
+ case XMM11_3: return myfpregs.xmm_space[47];
+ case XMM12_0: return myfpregs.xmm_space[48];
+ case XMM12_1: return myfpregs.xmm_space[49];
+ case XMM12_2: return myfpregs.xmm_space[50];
+ case XMM12_3: return myfpregs.xmm_space[51];
+ case XMM13_0: return myfpregs.xmm_space[52];
+ case XMM13_1: return myfpregs.xmm_space[53];
+ case XMM13_2: return myfpregs.xmm_space[54];
+ case XMM13_3: return myfpregs.xmm_space[55];
+ case XMM14_0: return myfpregs.xmm_space[56];
+ case XMM14_1: return myfpregs.xmm_space[57];
+ case XMM14_2: return myfpregs.xmm_space[58];
+ case XMM14_3: return myfpregs.xmm_space[59];
+ case XMM15_0: return myfpregs.xmm_space[60];
+ case XMM15_1: return myfpregs.xmm_space[61];
+ case XMM15_2: return myfpregs.xmm_space[62];
+ case XMM15_3: return myfpregs.xmm_space[63];
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+bool
+AMD64TraceChild::update(int pid)
+{
+ oldregs = regs;
+ oldfpregs = fpregs;
+ if (ptrace(PTRACE_GETREGS, pid, 0, ®s) != 0) {
+ cerr << "update: " << strerror(errno) << endl;
+ return false;
+ }
+ if (ptrace(PTRACE_GETFPREGS, pid, 0, &fpregs) != 0) {
+ cerr << "update: " << strerror(errno) << endl;
+ return false;
+ }
+ for (unsigned int x = 0; x < numregs; x++)
+ regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
+ return true;
+}
+
+AMD64TraceChild::AMD64TraceChild()
+{
+ for (unsigned int x = 0; x < numregs; x++)
+ regDiffSinceUpdate[x] = false;
+}
+
+int64_t
+AMD64TraceChild::getRegVal(int num)
+{
+ return getRegs(regs, fpregs, num);
+}
+
+int64_t
+AMD64TraceChild::getOldRegVal(int num)
+{
+ return getRegs(oldregs, oldfpregs, num);
+}
+
+ostream &
+AMD64TraceChild::outputStartState(ostream & os)
+{
+ uint64_t sp = getSP();
+ uint64_t pc = getPC();
+ uint64_t highestInfo = 0;
+ char obuf[1024];
+ sprintf(obuf, "Initial stack pointer = 0x%016lx\n", sp);
+ os << obuf;
+ sprintf(obuf, "Initial program counter = 0x%016lx\n", pc);
+ os << obuf;
+
+ //Output the argument count
+ uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ sprintf(obuf, "0x%016lx: Argc = 0x%016lx\n", sp, cargc);
+ os << obuf;
+ sp += 8;
+
+ //Output argv pointers
+ int argCount = 0;
+ uint64_t cargv;
+ do {
+ cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ sprintf(obuf, "0x%016lx: argv[%d] = 0x%016lx\n",
+ sp, argCount++, cargv);
+ if (cargv)
+ if (highestInfo < cargv)
+ highestInfo = cargv;
+ os << obuf;
+ sp += 8;
+ } while(cargv);
+
+ //Output the envp pointers
+ int envCount = 0;
+ uint64_t cenvp;
+ do {
+ cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ sprintf(obuf, "0x%016lx: envp[%d] = 0x%016lx\n",
+ sp, envCount++, cenvp);
+ os << obuf;
+ sp += 8;
+ } while(cenvp);
+ uint64_t auxType, auxVal;
+ do {
+ auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ sp += 8;
+ auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ sp += 8;
+ sprintf(obuf, "0x%016lx: Auxiliary vector = {0x%016lx, 0x%016lx}\n",
+ sp - 16, auxType, auxVal);
+ os << obuf;
+ } while(auxType != 0 || auxVal != 0);
+ //Print out the argument strings, environment strings, and file name.
+ string current;
+ uint64_t buf;
+ uint64_t currentStart = sp;
+ bool clearedInitialPadding = false;
+ do {
+ buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ char * cbuf = (char *)&buf;
+ for (int x = 0; x < sizeof(uint64_t); x++) {
+ if (cbuf[x])
+ current += cbuf[x];
+ else {
+ sprintf(obuf, "0x%016lx: \"%s\"\n",
+ currentStart, current.c_str());
+ os << obuf;
+ current = "";
+ currentStart = sp + x + 1;
+ }
+ }
+ sp += 8;
+ clearedInitialPadding = clearedInitialPadding || buf != 0;
+ } while (!clearedInitialPadding || buf != 0 || sp <= highestInfo);
+ return os;
+}
+
+uint64_t
+AMD64TraceChild::findSyscall()
+{
+ uint64_t rip = getPC();
+ bool foundOpcode = false;
+ bool twoByteOpcode = false;
+ for (;;) {
+ uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, rip, 0);
+ for (int i = 0; i < sizeof(uint64_t); i++) {
+ unsigned char byte = buf & 0xFF;
+ if (!foundOpcode) {
+ if(!(byte == 0x66 || //operand override
+ byte == 0x67 || //address override
+ byte == 0x2E || //cs
+ byte == 0x3E || //ds
+ byte == 0x26 || //es
+ byte == 0x64 || //fs
+ byte == 0x65 || //gs
+ byte == 0x36 || //ss
+ byte == 0xF0 || //lock
+ byte == 0xF2 || //repe
+ byte == 0xF3 || //repne
+ (byte >= 0x40 && byte <= 0x4F) // REX
+ )) {
+ foundOpcode = true;
+ }
+ }
+ if (foundOpcode) {
+ if (twoByteOpcode) {
+ //SYSCALL or SYSENTER
+ if (byte == 0x05 || byte == 0x34)
+ return rip + 1;
+ else
+ return 0;
+ }
+ if (!twoByteOpcode) {
+ if (byte == 0xCC) // INT3
+ return rip + 1;
+ else if (byte == 0xCD) // INT with byte immediate
+ return rip + 2;
+ else if (byte == 0x0F) // two byte opcode prefix
+ twoByteOpcode = true;
+ else
+ return 0;
+ }
+ }
+ buf >>= 8;
+ rip++;
+ }
+ }
+}
+
+bool
+AMD64TraceChild::step()
+{
+ uint64_t ripAfterSyscall = findSyscall();
+ if (ripAfterSyscall) {
+ //Get the original contents of memory
+ uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, ripAfterSyscall, 0);
+ //Patch the first two bytes of the memory immediately after this with
+ //jmp -2. Either single stepping will take over before this
+ //instruction, leaving the rip where it should be, or it will take
+ //over after this instruction, -still- leaving the rip where it should
+ //be.
+ uint64_t newBuf = (buf & ~0xFFFF) | 0xFEEB;
+ //Write the patched memory to the processes address space
+ ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, newBuf);
+ //Step and hit it
+ ptraceSingleStep();
+ //Put things back to the way they started
+ ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, buf);
+ } else {
+ //Get all the way past repe and repne string instructions in one shot.
+ uint64_t newPC, origPC = getPC();
+ do {
+ ptraceSingleStep();
+ newPC = getPC();
+ } while(newPC == origPC);
+ }
+}
+
+TraceChild * genTraceChild()
+{
+ return new AMD64TraceChild;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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(®s, 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, ®s) != 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;
+}
+
--- /dev/null
+/*
+ * 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
+
--- /dev/null
+/*
+ * 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, ®s) != 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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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, ®Val, sizeof(regVal)) == -1) {
+ cerr << "Write failed! " << strerror(errno) << endl;
+ tracing = false;
+ return false;
+ }
+ }
+ regVal = getRegVal(PC);
+ if (write(socket, ®Val, sizeof(regVal)) == -1) {
+ cerr << "Write failed! " << strerror(errno) << endl;
+ tracing = false;
+ return false;
+ }
+ regVal = getRegVal(NPC);
+ if (write(socket, ®Val, sizeof(regVal)) == -1) {
+ cerr << "Write failed! " << strerror(errno) << endl;
+ tracing = false;
+ return false;
+ }
+ regVal = getRegVal(CCR);
+ if (write(socket, ®Val, sizeof(regVal)) == -1) {
+ cerr << "Write failed! " << strerror(errno) << endl;
+ tracing = false;
+ return false;
+ }
+ return true;
+}
+
+int64_t
+getRegs(regs & myregs, fpu & myfpu, uint64_t * locals,
+ uint64_t * inputs, int num)
+{
+ assert(num < SparcTraceChild::numregs && num >= 0);
+ switch (num) {
+ //Global registers
+ case SparcTraceChild::G0: return 0;
+ case SparcTraceChild::G1: return myregs.r_g1;
+ case SparcTraceChild::G2: return myregs.r_g2;
+ case SparcTraceChild::G3: return myregs.r_g3;
+ case SparcTraceChild::G4: return myregs.r_g4;
+ case SparcTraceChild::G5: return myregs.r_g5;
+ case SparcTraceChild::G6: return myregs.r_g6;
+ case SparcTraceChild::G7: return myregs.r_g7;
+ //Output registers
+ case SparcTraceChild::O0: return myregs.r_o0;
+ case SparcTraceChild::O1: return myregs.r_o1;
+ case SparcTraceChild::O2: return myregs.r_o2;
+ case SparcTraceChild::O3: return myregs.r_o3;
+ case SparcTraceChild::O4: return myregs.r_o4;
+ case SparcTraceChild::O5: return myregs.r_o5;
+ case SparcTraceChild::O6: return myregs.r_o6;
+ case SparcTraceChild::O7: return myregs.r_o7;
+ //Local registers
+ case SparcTraceChild::L0: return locals[0];
+ case SparcTraceChild::L1: return locals[1];
+ case SparcTraceChild::L2: return locals[2];
+ case SparcTraceChild::L3: return locals[3];
+ case SparcTraceChild::L4: return locals[4];
+ case SparcTraceChild::L5: return locals[5];
+ case SparcTraceChild::L6: return locals[6];
+ case SparcTraceChild::L7: return locals[7];
+ //Input registers
+ case SparcTraceChild::I0: return inputs[0];
+ case SparcTraceChild::I1: return inputs[1];
+ case SparcTraceChild::I2: return inputs[2];
+ case SparcTraceChild::I3: return inputs[3];
+ case SparcTraceChild::I4: return inputs[4];
+ case SparcTraceChild::I5: return inputs[5];
+ case SparcTraceChild::I6: return inputs[6];
+ case SparcTraceChild::I7: return inputs[7];
+ //Floating point
+ case SparcTraceChild::F0: return myfpu.f_fpstatus.fpu_fr[0];
+ case SparcTraceChild::F2: return myfpu.f_fpstatus.fpu_fr[1];
+ case SparcTraceChild::F4: return myfpu.f_fpstatus.fpu_fr[2];
+ case SparcTraceChild::F6: return myfpu.f_fpstatus.fpu_fr[3];
+ case SparcTraceChild::F8: return myfpu.f_fpstatus.fpu_fr[4];
+ case SparcTraceChild::F10: return myfpu.f_fpstatus.fpu_fr[5];
+ case SparcTraceChild::F12: return myfpu.f_fpstatus.fpu_fr[6];
+ case SparcTraceChild::F14: return myfpu.f_fpstatus.fpu_fr[7];
+ case SparcTraceChild::F16: return myfpu.f_fpstatus.fpu_fr[8];
+ case SparcTraceChild::F18: return myfpu.f_fpstatus.fpu_fr[9];
+ case SparcTraceChild::F20: return myfpu.f_fpstatus.fpu_fr[10];
+ case SparcTraceChild::F22: return myfpu.f_fpstatus.fpu_fr[11];
+ case SparcTraceChild::F24: return myfpu.f_fpstatus.fpu_fr[12];
+ case SparcTraceChild::F26: return myfpu.f_fpstatus.fpu_fr[13];
+ case SparcTraceChild::F28: return myfpu.f_fpstatus.fpu_fr[14];
+ case SparcTraceChild::F30: return myfpu.f_fpstatus.fpu_fr[15];
+ case SparcTraceChild::F32: return myfpu.f_fpstatus.fpu_fr[16];
+ case SparcTraceChild::F34: return myfpu.f_fpstatus.fpu_fr[17];
+ case SparcTraceChild::F36: return myfpu.f_fpstatus.fpu_fr[18];
+ case SparcTraceChild::F38: return myfpu.f_fpstatus.fpu_fr[19];
+ case SparcTraceChild::F40: return myfpu.f_fpstatus.fpu_fr[20];
+ case SparcTraceChild::F42: return myfpu.f_fpstatus.fpu_fr[21];
+ case SparcTraceChild::F44: return myfpu.f_fpstatus.fpu_fr[22];
+ case SparcTraceChild::F46: return myfpu.f_fpstatus.fpu_fr[23];
+ case SparcTraceChild::F48: return myfpu.f_fpstatus.fpu_fr[24];
+ case SparcTraceChild::F50: return myfpu.f_fpstatus.fpu_fr[25];
+ case SparcTraceChild::F52: return myfpu.f_fpstatus.fpu_fr[26];
+ case SparcTraceChild::F54: return myfpu.f_fpstatus.fpu_fr[27];
+ case SparcTraceChild::F56: return myfpu.f_fpstatus.fpu_fr[28];
+ case SparcTraceChild::F58: return myfpu.f_fpstatus.fpu_fr[29];
+ case SparcTraceChild::F60: return myfpu.f_fpstatus.fpu_fr[30];
+ case SparcTraceChild::F62: return myfpu.f_fpstatus.fpu_fr[31];
+ //Miscelaneous
+ case SparcTraceChild::FSR: return myfpu.f_fpstatus.Fpu_fsr;
+ case SparcTraceChild::FPRS: return myregs.r_fprs;
+ case SparcTraceChild::PC: return myregs.r_tpc;
+ case SparcTraceChild::NPC: return myregs.r_tnpc;
+ case SparcTraceChild::Y: return myregs.r_y;
+ case SparcTraceChild::CWP:
+ return (myregs.r_tstate >> 0) & ((1 << 5) - 1);
+ case SparcTraceChild::PSTATE:
+ return (myregs.r_tstate >> 8) & ((1 << 13) - 1);
+ case SparcTraceChild::ASI:
+ return (myregs.r_tstate >> 24) & ((1 << 8) - 1);
+ case SparcTraceChild::CCR:
+ return (myregs.r_tstate >> 32) & ((1 << 8) - 1);
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+bool
+SparcTraceChild::update(int pid)
+{
+ memcpy(&oldregs, &theregs, sizeof(regs));
+ memcpy(&oldfpregs, &thefpregs, sizeof(fpu));
+ memcpy(oldLocals, locals, 8 * sizeof(uint64_t));
+ memcpy(oldInputs, inputs, 8 * sizeof(uint64_t));
+ if (ptrace(PTRACE_GETREGS, pid, &theregs, 0) != 0) {
+ cerr << "Update failed" << endl;
+ return false;
+ }
+ uint64_t stackPointer = getSP();
+ uint64_t stackBias = 2047;
+ bool v9 = stackPointer % 2;
+ for (unsigned int x = 0; x < 8; x++) {
+ uint64_t localAddr = stackPointer +
+ (v9 ? (stackBias + x * 8) : (x * 4));
+ locals[x] = ptrace(PTRACE_PEEKTEXT, pid, localAddr, 0);
+ if (!v9) locals[x] >>= 32;
+ uint64_t inputAddr = stackPointer +
+ (v9 ? (stackBias + x * 8 + (8 * 8)) : (x * 4 + 8 * 4));
+ inputs[x] = ptrace(PTRACE_PEEKTEXT, pid, inputAddr, 0);
+ if (!v9) inputs[x] >>= 32;
+ }
+ if (ptrace(PTRACE_GETFPREGS, pid, &thefpregs, 0) != 0)
+ return false;
+ for (unsigned int x = 0; x < numregs; x++)
+ regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
+ return true;
+}
+
+SparcTraceChild::SparcTraceChild()
+{
+ for (unsigned int x = 0; x < numregs; x++)
+ regDiffSinceUpdate[x] = false;
+}
+
+int
+SparcTraceChild::getTargets(uint32_t inst, uint64_t pc, uint64_t npc,
+ uint64_t &target1, uint64_t &target2)
+{
+ //We can identify the instruction categories we care about using the top
+ //10 bits of the instruction, excluding the annul bit in the 3rd most
+ //significant bit position and the condition field. We'll call these
+ //bits the "sig" for signature.
+ uint32_t sig = (inst >> 22) & 0x307;
+ uint32_t cond = (inst >> 25) & 0xf;
+ bool annul = (inst & (1 << 29));
+
+ //Check if it's a ba...
+ bool ba = (cond == 0x8) &&
+ (sig == 0x1 || sig == 0x2 || sig == 0x5 || sig == 0x6);
+ //or a bn...
+ bool bn = (cond == 0x0) &&
+ (sig == 0x1 || sig == 0x2 || sig == 0x5 || sig == 0x6);
+ //or a bcc
+ bool bcc = (cond & 0x7) &&
+ (sig == 0x1 || sig == 0x2 || sig == 0x3 || sig == 0x5 || sig == 0x6);
+
+ if (annul) {
+ if (bcc) {
+ target1 = npc;
+ target2 = npc + 4;
+ return 2;
+ } else if(ba) {
+ //This branches immediately to the effective address of the branch
+ //which we'll have to calculate.
+ uint64_t disp = 0;
+ int64_t extender = 0;
+ //Figure out how big the displacement field is, and grab the bits
+ if (sig == 0x1 || sig == 0x5) {
+ disp = inst & ((1 << 19) - 1);
+ extender = 1 << 18;
+ } else {
+ disp = inst & ((1 << 22) - 1);
+ extender = 1 << 21;
+ }
+ //This does sign extension, believe it or not.
+ disp = (disp ^ extender) - extender;
+ //Multiply the displacement by 4. I'm assuming the compiler is
+ //smart enough to turn this into a shift.
+ disp *= 4;
+ target1 = pc + disp;
+ } else if(bn)
+ target1 = npc + 4;
+ else
+ target1 = npc;
+ return 1;
+ } else {
+ target1 = npc;
+ return 1;
+ }
+}
+
+bool
+SparcTraceChild::step()
+{
+ //Increment the count of the number of instructions executed
+ instructions++;
+ //Two important considerations are that the address of the instruction
+ //being breakpointed should be word (64bit) aligned, and that both the
+ //next instruction and the instruction after that need to be breakpointed
+ //so that annulled branches will still stop as well.
+
+ /*
+ * Useful constants
+ */
+ const static uint64_t breakInst = 0x91d02001;
+ const static uint64_t lowBreakInst = breakInst;
+ const static uint64_t highBreakInst = breakInst << 32;
+ const static uint64_t breakWord = breakInst | (breakInst << 32);
+ const static uint64_t lowMask = 0xFFFFFFFFULL;
+ const static uint64_t highMask = lowMask << 32;
+
+ /*
+ * storage for the original contents of the child process's memory
+ */
+ uint64_t originalInst, originalAnnulInst;
+
+ /*
+ * Get information about where the process is and is headed next.
+ */
+ uint64_t currentPC = getRegVal(PC);
+ bool unalignedPC = currentPC & 7;
+ uint64_t alignedPC = currentPC & (~7);
+ uint64_t nextPC = getRegVal(NPC);
+ bool unalignedNPC = nextPC & 7;
+ uint64_t alignedNPC = nextPC & (~7);
+
+ //Get the current instruction
+ uint64_t curInst = ptrace(PTRACE_PEEKTEXT, pid, alignedPC);
+ curInst = unalignedPC ? (curInst & 0xffffffffULL) : (curInst >> 32);
+
+ uint64_t bp1, bp2;
+ int numTargets = getTargets(curInst, currentPC, nextPC, bp1, bp2);
+ assert(numTargets == 1 || numTargets == 2);
+
+ bool unalignedBp1 = bp1 & 7;
+ uint64_t alignedBp1 = bp1 & (~7);
+ bool unalignedBp2 = bp2 & 7;
+ uint64_t alignedBp2 = bp2 & (~7);
+ uint64_t origBp1, origBp2;
+
+ /*
+ * Set the first breakpoint
+ */
+ origBp1 = ptrace(PTRACE_PEEKTEXT, pid, alignedBp1, 0);
+ uint64_t newBp1 = origBp1;
+ newBp1 &= unalignedBp1 ? highMask : lowMask;
+ newBp1 |= unalignedBp1 ? lowBreakInst : highBreakInst;
+ if (ptrace(PTRACE_POKETEXT, pid, alignedBp1, newBp1) != 0)
+ cerr << "Poke failed" << endl;
+ /*
+ * Set the second breakpoint if necessary
+ */
+ if (numTargets == 2) {
+ origBp2 = ptrace(PTRACE_PEEKTEXT, pid, alignedBp2, 0);
+ uint64_t newBp2 = origBp2;
+ newBp2 &= unalignedBp2 ? highMask : lowMask;
+ newBp2 |= unalignedBp2 ? lowBreakInst : highBreakInst;
+ if (ptrace(PTRACE_POKETEXT, pid, alignedBp2, newBp2) != 0)
+ cerr << "Poke failed" << endl;
+ }
+
+ /*
+ * Restart the child process
+ */
+ //Note that the "addr" parameter is supposed to be ignored, but in at
+ //least one version of the kernel, it must be 1 or it will set what
+ //pc to continue from
+ if (ptrace(PTRACE_CONT, pid, 1, 0) != 0)
+ cerr << "Cont failed" << endl;
+ doWait();
+
+ /*
+ * Update our record of the child's state
+ */
+ update(pid);
+
+ /*
+ * Put back the original contents of the childs address space in the
+ * reverse order.
+ */
+ if (numTargets == 2) {
+ if (ptrace(PTRACE_POKETEXT, pid, alignedBp2, origBp2) != 0)
+ cerr << "Poke failed" << endl;
+ }
+ if (ptrace(PTRACE_POKETEXT, pid, alignedBp1, origBp1) != 0)
+ cerr << "Poke failed" << endl;
+}
+
+int64_t
+SparcTraceChild::getRegVal(int num)
+{
+ return getRegs(theregs, thefpregs, locals, inputs, num);
+}
+
+int64_t
+SparcTraceChild::getOldRegVal(int num)
+{
+ return getRegs(oldregs, oldfpregs, oldLocals, oldInputs, num);
+}
+
+ostream &
+SparcTraceChild::outputStartState(ostream & os)
+{
+ bool v8 = false;
+ uint64_t sp = getSP();
+ if (sp % 2) {
+ os << "Detected a 64 bit executable.\n";
+ v8 = false;
+ } else {
+ os << "Detected a 32 bit executable.\n";
+ v8 = true;
+ }
+ uint64_t pc = getPC();
+ char obuf[1024];
+ sprintf(obuf, "Initial stack pointer = 0x%016llx\n", sp);
+ os << obuf;
+ sprintf(obuf, "Initial program counter = 0x%016llx\n", pc);
+ os << obuf;
+ if (!v8) {
+ //Take out the stack bias
+ sp += 2047;
+ }
+ //Output the window save area
+ for (unsigned int x = 0; x < 16; x++) {
+ uint64_t regspot = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ if (v8) regspot = regspot >> 32;
+ sprintf(obuf, "0x%016llx: Window save %d = 0x%016llx\n",
+ sp, x+1, regspot);
+ os << obuf;
+ sp += v8 ? 4 : 8;
+ }
+ //Output the argument count
+ uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ if (v8) cargc = cargc >> 32;
+ sprintf(obuf, "0x%016llx: Argc = 0x%016llx\n", sp, cargc);
+ os << obuf;
+ sp += v8 ? 4 : 8;
+ //Output argv pointers
+ int argCount = 0;
+ uint64_t cargv;
+ do {
+ cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ if (v8) cargv = cargv >> 32;
+ sprintf(obuf, "0x%016llx: argv[%d] = 0x%016llx\n",
+ sp, argCount++, cargv);
+ os << obuf;
+ sp += v8 ? 4 : 8;
+ } while(cargv);
+ //Output the envp pointers
+ int envCount = 0;
+ uint64_t cenvp;
+ do {
+ cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ if (v8) cenvp = cenvp >> 32;
+ sprintf(obuf, "0x%016llx: envp[%d] = 0x%016llx\n",
+ sp, envCount++, cenvp);
+ os << obuf;
+ sp += v8 ? 4 : 8;
+ } while (cenvp);
+ uint64_t auxType, auxVal;
+ do {
+ auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ if (v8) auxType = auxType >> 32;
+ sp += (v8 ? 4 : 8);
+ auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ if (v8) auxVal = auxVal >> 32;
+ sp += (v8 ? 4 : 8);
+ sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n",
+ sp - 8, auxType, auxVal);
+ os << obuf;
+ } while (auxType != 0 || auxVal != 0);
+ //Print out the argument strings, environment strings, and file name.
+ string current;
+ uint64_t buf;
+ uint64_t currentStart = sp;
+ bool clearedInitialPadding = false;
+ do {
+ buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ char * cbuf = (char *)&buf;
+ for (int x = 0; x < sizeof(uint32_t); x++) {
+ if (cbuf[x])
+ current += cbuf[x];
+ else {
+ sprintf(obuf, "0x%016llx: \"%s\"\n",
+ currentStart, current.c_str());
+ os << obuf;
+ current = "";
+ currentStart = sp + x + 1;
+ }
+ }
+ sp += (v8 ? 4 : 8);
+ clearedInitialPadding = clearedInitialPadding || buf != 0;
+ } while (!clearedInitialPadding || buf != 0);
+ return os;
+}
+
+TraceChild *
+genTraceChild()
+{
+ return new SparcTraceChild;
+}
+
--- /dev/null
+/*
+ * 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
+++ /dev/null
-/*
- * 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, ®Val64, sizeof(regVal64)) == -1) {
- cerr << "Write failed! " << strerror(errno) << endl;
- tracing = false;
- return false;
- }
- }
- regVal64 = getRegVal(RIP);
- if (write(socket, ®Val64, sizeof(regVal64)) == -1) {
- cerr << "Write failed! " << strerror(errno) << endl;
- tracing = false;
- return false;
- }
- for (int x = MMX0_0; x <= MMX7_1; x++) {
- regVal32 = getRegVal(x);
- if (write(socket, ®Val32, sizeof(regVal32)) == -1) {
- cerr << "Write failed! " << strerror(errno) << endl;
- tracing = false;
- return false;
- }
- }
- for (int x = XMM0_0; x <= XMM15_3; x++) {
- regVal32 = getRegVal(x);
- if (write(socket, ®Val32, sizeof(regVal32)) == -1) {
- cerr << "Write failed! " << strerror(errno) << endl;
- tracing = false;
- return false;
- }
- }
- return true;
-}
-
-int64_t
-AMD64TraceChild::getRegs(user_regs_struct & myregs,
- user_fpregs_struct & myfpregs, int num)
-{
- assert(num < numregs && num >= 0);
- switch (num) {
- //GPRs
- case RAX: return myregs.rax;
- case RBX: return myregs.rbx;
- case RCX: return myregs.rcx;
- case RDX: return myregs.rdx;
- //Index registers
- case RSI: return myregs.rsi;
- case RDI: return myregs.rdi;
- //Base pointer and stack pointer
- case RBP: return myregs.rbp;
- case RSP: return myregs.rsp;
- //New 64 bit mode registers
- case R8: return myregs.r8;
- case R9: return myregs.r9;
- case R10: return myregs.r10;
- case R11: return myregs.r11;
- case R12: return myregs.r12;
- case R13: return myregs.r13;
- case R14: return myregs.r14;
- case R15: return myregs.r15;
- //Segmentation registers
- case CS: return myregs.cs;
- case DS: return myregs.ds;
- case ES: return myregs.es;
- case FS: return myregs.fs;
- case GS: return myregs.gs;
- case SS: return myregs.ss;
- case FS_BASE: return myregs.fs_base;
- case GS_BASE: return myregs.gs_base;
- //PC
- case RIP: return myregs.rip;
- //Flags
- case EFLAGS: return myregs.eflags;
- //MMX
- case MMX0_0: return myfpregs.st_space[0];
- case MMX0_1: return myfpregs.st_space[1];
- case MMX1_0: return myfpregs.st_space[2];
- case MMX1_1: return myfpregs.st_space[3];
- case MMX2_0: return myfpregs.st_space[4];
- case MMX2_1: return myfpregs.st_space[5];
- case MMX3_0: return myfpregs.st_space[6];
- case MMX3_1: return myfpregs.st_space[7];
- case MMX4_0: return myfpregs.st_space[8];
- case MMX4_1: return myfpregs.st_space[9];
- case MMX5_0: return myfpregs.st_space[10];
- case MMX5_1: return myfpregs.st_space[11];
- case MMX6_0: return myfpregs.st_space[12];
- case MMX6_1: return myfpregs.st_space[13];
- case MMX7_0: return myfpregs.st_space[14];
- case MMX7_1: return myfpregs.st_space[15];
- //XMM
- case XMM0_0: return myfpregs.xmm_space[0];
- case XMM0_1: return myfpregs.xmm_space[1];
- case XMM0_2: return myfpregs.xmm_space[2];
- case XMM0_3: return myfpregs.xmm_space[3];
- case XMM1_0: return myfpregs.xmm_space[4];
- case XMM1_1: return myfpregs.xmm_space[5];
- case XMM1_2: return myfpregs.xmm_space[6];
- case XMM1_3: return myfpregs.xmm_space[7];
- case XMM2_0: return myfpregs.xmm_space[8];
- case XMM2_1: return myfpregs.xmm_space[9];
- case XMM2_2: return myfpregs.xmm_space[10];
- case XMM2_3: return myfpregs.xmm_space[11];
- case XMM3_0: return myfpregs.xmm_space[12];
- case XMM3_1: return myfpregs.xmm_space[13];
- case XMM3_2: return myfpregs.xmm_space[14];
- case XMM3_3: return myfpregs.xmm_space[15];
- case XMM4_0: return myfpregs.xmm_space[16];
- case XMM4_1: return myfpregs.xmm_space[17];
- case XMM4_2: return myfpregs.xmm_space[18];
- case XMM4_3: return myfpregs.xmm_space[19];
- case XMM5_0: return myfpregs.xmm_space[20];
- case XMM5_1: return myfpregs.xmm_space[21];
- case XMM5_2: return myfpregs.xmm_space[22];
- case XMM5_3: return myfpregs.xmm_space[23];
- case XMM6_0: return myfpregs.xmm_space[24];
- case XMM6_1: return myfpregs.xmm_space[25];
- case XMM6_2: return myfpregs.xmm_space[26];
- case XMM6_3: return myfpregs.xmm_space[27];
- case XMM7_0: return myfpregs.xmm_space[28];
- case XMM7_1: return myfpregs.xmm_space[29];
- case XMM7_2: return myfpregs.xmm_space[30];
- case XMM7_3: return myfpregs.xmm_space[31];
- case XMM8_0: return myfpregs.xmm_space[32];
- case XMM8_1: return myfpregs.xmm_space[33];
- case XMM8_2: return myfpregs.xmm_space[34];
- case XMM8_3: return myfpregs.xmm_space[35];
- case XMM9_0: return myfpregs.xmm_space[36];
- case XMM9_1: return myfpregs.xmm_space[37];
- case XMM9_2: return myfpregs.xmm_space[38];
- case XMM9_3: return myfpregs.xmm_space[39];
- case XMM10_0: return myfpregs.xmm_space[40];
- case XMM10_1: return myfpregs.xmm_space[41];
- case XMM10_2: return myfpregs.xmm_space[42];
- case XMM10_3: return myfpregs.xmm_space[43];
- case XMM11_0: return myfpregs.xmm_space[44];
- case XMM11_1: return myfpregs.xmm_space[45];
- case XMM11_2: return myfpregs.xmm_space[46];
- case XMM11_3: return myfpregs.xmm_space[47];
- case XMM12_0: return myfpregs.xmm_space[48];
- case XMM12_1: return myfpregs.xmm_space[49];
- case XMM12_2: return myfpregs.xmm_space[50];
- case XMM12_3: return myfpregs.xmm_space[51];
- case XMM13_0: return myfpregs.xmm_space[52];
- case XMM13_1: return myfpregs.xmm_space[53];
- case XMM13_2: return myfpregs.xmm_space[54];
- case XMM13_3: return myfpregs.xmm_space[55];
- case XMM14_0: return myfpregs.xmm_space[56];
- case XMM14_1: return myfpregs.xmm_space[57];
- case XMM14_2: return myfpregs.xmm_space[58];
- case XMM14_3: return myfpregs.xmm_space[59];
- case XMM15_0: return myfpregs.xmm_space[60];
- case XMM15_1: return myfpregs.xmm_space[61];
- case XMM15_2: return myfpregs.xmm_space[62];
- case XMM15_3: return myfpregs.xmm_space[63];
- default:
- assert(0);
- return 0;
- }
-}
-
-bool
-AMD64TraceChild::update(int pid)
-{
- oldregs = regs;
- oldfpregs = fpregs;
- if (ptrace(PTRACE_GETREGS, pid, 0, ®s) != 0) {
- cerr << "update: " << strerror(errno) << endl;
- return false;
- }
- if (ptrace(PTRACE_GETFPREGS, pid, 0, &fpregs) != 0) {
- cerr << "update: " << strerror(errno) << endl;
- return false;
- }
- for (unsigned int x = 0; x < numregs; x++)
- regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
- return true;
-}
-
-AMD64TraceChild::AMD64TraceChild()
-{
- for (unsigned int x = 0; x < numregs; x++)
- regDiffSinceUpdate[x] = false;
-}
-
-int64_t
-AMD64TraceChild::getRegVal(int num)
-{
- return getRegs(regs, fpregs, num);
-}
-
-int64_t
-AMD64TraceChild::getOldRegVal(int num)
-{
- return getRegs(oldregs, oldfpregs, num);
-}
-
-ostream &
-AMD64TraceChild::outputStartState(ostream & os)
-{
- uint64_t sp = getSP();
- uint64_t pc = getPC();
- uint64_t highestInfo = 0;
- char obuf[1024];
- sprintf(obuf, "Initial stack pointer = 0x%016lx\n", sp);
- os << obuf;
- sprintf(obuf, "Initial program counter = 0x%016lx\n", pc);
- os << obuf;
-
- //Output the argument count
- uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
- sprintf(obuf, "0x%016lx: Argc = 0x%016lx\n", sp, cargc);
- os << obuf;
- sp += 8;
-
- //Output argv pointers
- int argCount = 0;
- uint64_t cargv;
- do {
- cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
- sprintf(obuf, "0x%016lx: argv[%d] = 0x%016lx\n",
- sp, argCount++, cargv);
- if (cargv)
- if (highestInfo < cargv)
- highestInfo = cargv;
- os << obuf;
- sp += 8;
- } while(cargv);
-
- //Output the envp pointers
- int envCount = 0;
- uint64_t cenvp;
- do {
- cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
- sprintf(obuf, "0x%016lx: envp[%d] = 0x%016lx\n",
- sp, envCount++, cenvp);
- os << obuf;
- sp += 8;
- } while(cenvp);
- uint64_t auxType, auxVal;
- do {
- auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
- sp += 8;
- auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
- sp += 8;
- sprintf(obuf, "0x%016lx: Auxiliary vector = {0x%016lx, 0x%016lx}\n",
- sp - 16, auxType, auxVal);
- os << obuf;
- } while(auxType != 0 || auxVal != 0);
- //Print out the argument strings, environment strings, and file name.
- string current;
- uint64_t buf;
- uint64_t currentStart = sp;
- bool clearedInitialPadding = false;
- do {
- buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
- char * cbuf = (char *)&buf;
- for (int x = 0; x < sizeof(uint64_t); x++) {
- if (cbuf[x])
- current += cbuf[x];
- else {
- sprintf(obuf, "0x%016lx: \"%s\"\n",
- currentStart, current.c_str());
- os << obuf;
- current = "";
- currentStart = sp + x + 1;
- }
- }
- sp += 8;
- clearedInitialPadding = clearedInitialPadding || buf != 0;
- } while (!clearedInitialPadding || buf != 0 || sp <= highestInfo);
- return os;
-}
-
-uint64_t
-AMD64TraceChild::findSyscall()
-{
- uint64_t rip = getPC();
- bool foundOpcode = false;
- bool twoByteOpcode = false;
- for (;;) {
- uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, rip, 0);
- for (int i = 0; i < sizeof(uint64_t); i++) {
- unsigned char byte = buf & 0xFF;
- if (!foundOpcode) {
- if(!(byte == 0x66 || //operand override
- byte == 0x67 || //address override
- byte == 0x2E || //cs
- byte == 0x3E || //ds
- byte == 0x26 || //es
- byte == 0x64 || //fs
- byte == 0x65 || //gs
- byte == 0x36 || //ss
- byte == 0xF0 || //lock
- byte == 0xF2 || //repe
- byte == 0xF3 || //repne
- (byte >= 0x40 && byte <= 0x4F) // REX
- )) {
- foundOpcode = true;
- }
- }
- if (foundOpcode) {
- if (twoByteOpcode) {
- //SYSCALL or SYSENTER
- if (byte == 0x05 || byte == 0x34)
- return rip + 1;
- else
- return 0;
- }
- if (!twoByteOpcode) {
- if (byte == 0xCC) // INT3
- return rip + 1;
- else if (byte == 0xCD) // INT with byte immediate
- return rip + 2;
- else if (byte == 0x0F) // two byte opcode prefix
- twoByteOpcode = true;
- else
- return 0;
- }
- }
- buf >>= 8;
- rip++;
- }
- }
-}
-
-bool
-AMD64TraceChild::step()
-{
- uint64_t ripAfterSyscall = findSyscall();
- if (ripAfterSyscall) {
- //Get the original contents of memory
- uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, ripAfterSyscall, 0);
- //Patch the first two bytes of the memory immediately after this with
- //jmp -2. Either single stepping will take over before this
- //instruction, leaving the rip where it should be, or it will take
- //over after this instruction, -still- leaving the rip where it should
- //be.
- uint64_t newBuf = (buf & ~0xFFFF) | 0xFEEB;
- //Write the patched memory to the processes address space
- ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, newBuf);
- //Step and hit it
- ptraceSingleStep();
- //Put things back to the way they started
- ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, buf);
- } else {
- //Get all the way past repe and repne string instructions in one shot.
- uint64_t newPC, origPC = getPC();
- do {
- ptraceSingleStep();
- newPC = getPC();
- } while(newPC == origPC);
- }
-}
-
-TraceChild * genTraceChild()
-{
- return new AMD64TraceChild;
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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(®s, 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, ®s) != 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;
-}
-
+++ /dev/null
-/*
- * 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
-
+++ /dev/null
-/*
- * 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, ®s) != 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;
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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, ®Val, sizeof(regVal)) == -1) {
- cerr << "Write failed! " << strerror(errno) << endl;
- tracing = false;
- return false;
- }
- }
- regVal = getRegVal(PC);
- if (write(socket, ®Val, sizeof(regVal)) == -1) {
- cerr << "Write failed! " << strerror(errno) << endl;
- tracing = false;
- return false;
- }
- regVal = getRegVal(NPC);
- if (write(socket, ®Val, sizeof(regVal)) == -1) {
- cerr << "Write failed! " << strerror(errno) << endl;
- tracing = false;
- return false;
- }
- regVal = getRegVal(CCR);
- if (write(socket, ®Val, sizeof(regVal)) == -1) {
- cerr << "Write failed! " << strerror(errno) << endl;
- tracing = false;
- return false;
- }
- return true;
-}
-
-int64_t
-getRegs(regs & myregs, fpu & myfpu, uint64_t * locals,
- uint64_t * inputs, int num)
-{
- assert(num < SparcTraceChild::numregs && num >= 0);
- switch (num) {
- //Global registers
- case SparcTraceChild::G0: return 0;
- case SparcTraceChild::G1: return myregs.r_g1;
- case SparcTraceChild::G2: return myregs.r_g2;
- case SparcTraceChild::G3: return myregs.r_g3;
- case SparcTraceChild::G4: return myregs.r_g4;
- case SparcTraceChild::G5: return myregs.r_g5;
- case SparcTraceChild::G6: return myregs.r_g6;
- case SparcTraceChild::G7: return myregs.r_g7;
- //Output registers
- case SparcTraceChild::O0: return myregs.r_o0;
- case SparcTraceChild::O1: return myregs.r_o1;
- case SparcTraceChild::O2: return myregs.r_o2;
- case SparcTraceChild::O3: return myregs.r_o3;
- case SparcTraceChild::O4: return myregs.r_o4;
- case SparcTraceChild::O5: return myregs.r_o5;
- case SparcTraceChild::O6: return myregs.r_o6;
- case SparcTraceChild::O7: return myregs.r_o7;
- //Local registers
- case SparcTraceChild::L0: return locals[0];
- case SparcTraceChild::L1: return locals[1];
- case SparcTraceChild::L2: return locals[2];
- case SparcTraceChild::L3: return locals[3];
- case SparcTraceChild::L4: return locals[4];
- case SparcTraceChild::L5: return locals[5];
- case SparcTraceChild::L6: return locals[6];
- case SparcTraceChild::L7: return locals[7];
- //Input registers
- case SparcTraceChild::I0: return inputs[0];
- case SparcTraceChild::I1: return inputs[1];
- case SparcTraceChild::I2: return inputs[2];
- case SparcTraceChild::I3: return inputs[3];
- case SparcTraceChild::I4: return inputs[4];
- case SparcTraceChild::I5: return inputs[5];
- case SparcTraceChild::I6: return inputs[6];
- case SparcTraceChild::I7: return inputs[7];
- //Floating point
- case SparcTraceChild::F0: return myfpu.f_fpstatus.fpu_fr[0];
- case SparcTraceChild::F2: return myfpu.f_fpstatus.fpu_fr[1];
- case SparcTraceChild::F4: return myfpu.f_fpstatus.fpu_fr[2];
- case SparcTraceChild::F6: return myfpu.f_fpstatus.fpu_fr[3];
- case SparcTraceChild::F8: return myfpu.f_fpstatus.fpu_fr[4];
- case SparcTraceChild::F10: return myfpu.f_fpstatus.fpu_fr[5];
- case SparcTraceChild::F12: return myfpu.f_fpstatus.fpu_fr[6];
- case SparcTraceChild::F14: return myfpu.f_fpstatus.fpu_fr[7];
- case SparcTraceChild::F16: return myfpu.f_fpstatus.fpu_fr[8];
- case SparcTraceChild::F18: return myfpu.f_fpstatus.fpu_fr[9];
- case SparcTraceChild::F20: return myfpu.f_fpstatus.fpu_fr[10];
- case SparcTraceChild::F22: return myfpu.f_fpstatus.fpu_fr[11];
- case SparcTraceChild::F24: return myfpu.f_fpstatus.fpu_fr[12];
- case SparcTraceChild::F26: return myfpu.f_fpstatus.fpu_fr[13];
- case SparcTraceChild::F28: return myfpu.f_fpstatus.fpu_fr[14];
- case SparcTraceChild::F30: return myfpu.f_fpstatus.fpu_fr[15];
- case SparcTraceChild::F32: return myfpu.f_fpstatus.fpu_fr[16];
- case SparcTraceChild::F34: return myfpu.f_fpstatus.fpu_fr[17];
- case SparcTraceChild::F36: return myfpu.f_fpstatus.fpu_fr[18];
- case SparcTraceChild::F38: return myfpu.f_fpstatus.fpu_fr[19];
- case SparcTraceChild::F40: return myfpu.f_fpstatus.fpu_fr[20];
- case SparcTraceChild::F42: return myfpu.f_fpstatus.fpu_fr[21];
- case SparcTraceChild::F44: return myfpu.f_fpstatus.fpu_fr[22];
- case SparcTraceChild::F46: return myfpu.f_fpstatus.fpu_fr[23];
- case SparcTraceChild::F48: return myfpu.f_fpstatus.fpu_fr[24];
- case SparcTraceChild::F50: return myfpu.f_fpstatus.fpu_fr[25];
- case SparcTraceChild::F52: return myfpu.f_fpstatus.fpu_fr[26];
- case SparcTraceChild::F54: return myfpu.f_fpstatus.fpu_fr[27];
- case SparcTraceChild::F56: return myfpu.f_fpstatus.fpu_fr[28];
- case SparcTraceChild::F58: return myfpu.f_fpstatus.fpu_fr[29];
- case SparcTraceChild::F60: return myfpu.f_fpstatus.fpu_fr[30];
- case SparcTraceChild::F62: return myfpu.f_fpstatus.fpu_fr[31];
- //Miscelaneous
- case SparcTraceChild::FSR: return myfpu.f_fpstatus.Fpu_fsr;
- case SparcTraceChild::FPRS: return myregs.r_fprs;
- case SparcTraceChild::PC: return myregs.r_tpc;
- case SparcTraceChild::NPC: return myregs.r_tnpc;
- case SparcTraceChild::Y: return myregs.r_y;
- case SparcTraceChild::CWP:
- return (myregs.r_tstate >> 0) & ((1 << 5) - 1);
- case SparcTraceChild::PSTATE:
- return (myregs.r_tstate >> 8) & ((1 << 13) - 1);
- case SparcTraceChild::ASI:
- return (myregs.r_tstate >> 24) & ((1 << 8) - 1);
- case SparcTraceChild::CCR:
- return (myregs.r_tstate >> 32) & ((1 << 8) - 1);
- default:
- assert(0);
- return 0;
- }
-}
-
-bool
-SparcTraceChild::update(int pid)
-{
- memcpy(&oldregs, &theregs, sizeof(regs));
- memcpy(&oldfpregs, &thefpregs, sizeof(fpu));
- memcpy(oldLocals, locals, 8 * sizeof(uint64_t));
- memcpy(oldInputs, inputs, 8 * sizeof(uint64_t));
- if (ptrace(PTRACE_GETREGS, pid, &theregs, 0) != 0) {
- cerr << "Update failed" << endl;
- return false;
- }
- uint64_t stackPointer = getSP();
- uint64_t stackBias = 2047;
- bool v9 = stackPointer % 2;
- for (unsigned int x = 0; x < 8; x++) {
- uint64_t localAddr = stackPointer +
- (v9 ? (stackBias + x * 8) : (x * 4));
- locals[x] = ptrace(PTRACE_PEEKTEXT, pid, localAddr, 0);
- if (!v9) locals[x] >>= 32;
- uint64_t inputAddr = stackPointer +
- (v9 ? (stackBias + x * 8 + (8 * 8)) : (x * 4 + 8 * 4));
- inputs[x] = ptrace(PTRACE_PEEKTEXT, pid, inputAddr, 0);
- if (!v9) inputs[x] >>= 32;
- }
- if (ptrace(PTRACE_GETFPREGS, pid, &thefpregs, 0) != 0)
- return false;
- for (unsigned int x = 0; x < numregs; x++)
- regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
- return true;
-}
-
-SparcTraceChild::SparcTraceChild()
-{
- for (unsigned int x = 0; x < numregs; x++)
- regDiffSinceUpdate[x] = false;
-}
-
-int
-SparcTraceChild::getTargets(uint32_t inst, uint64_t pc, uint64_t npc,
- uint64_t &target1, uint64_t &target2)
-{
- //We can identify the instruction categories we care about using the top
- //10 bits of the instruction, excluding the annul bit in the 3rd most
- //significant bit position and the condition field. We'll call these
- //bits the "sig" for signature.
- uint32_t sig = (inst >> 22) & 0x307;
- uint32_t cond = (inst >> 25) & 0xf;
- bool annul = (inst & (1 << 29));
-
- //Check if it's a ba...
- bool ba = (cond == 0x8) &&
- (sig == 0x1 || sig == 0x2 || sig == 0x5 || sig == 0x6);
- //or a bn...
- bool bn = (cond == 0x0) &&
- (sig == 0x1 || sig == 0x2 || sig == 0x5 || sig == 0x6);
- //or a bcc
- bool bcc = (cond & 0x7) &&
- (sig == 0x1 || sig == 0x2 || sig == 0x3 || sig == 0x5 || sig == 0x6);
-
- if (annul) {
- if (bcc) {
- target1 = npc;
- target2 = npc + 4;
- return 2;
- } else if(ba) {
- //This branches immediately to the effective address of the branch
- //which we'll have to calculate.
- uint64_t disp = 0;
- int64_t extender = 0;
- //Figure out how big the displacement field is, and grab the bits
- if (sig == 0x1 || sig == 0x5) {
- disp = inst & ((1 << 19) - 1);
- extender = 1 << 18;
- } else {
- disp = inst & ((1 << 22) - 1);
- extender = 1 << 21;
- }
- //This does sign extension, believe it or not.
- disp = (disp ^ extender) - extender;
- //Multiply the displacement by 4. I'm assuming the compiler is
- //smart enough to turn this into a shift.
- disp *= 4;
- target1 = pc + disp;
- } else if(bn)
- target1 = npc + 4;
- else
- target1 = npc;
- return 1;
- } else {
- target1 = npc;
- return 1;
- }
-}
-
-bool
-SparcTraceChild::step()
-{
- //Increment the count of the number of instructions executed
- instructions++;
- //Two important considerations are that the address of the instruction
- //being breakpointed should be word (64bit) aligned, and that both the
- //next instruction and the instruction after that need to be breakpointed
- //so that annulled branches will still stop as well.
-
- /*
- * Useful constants
- */
- const static uint64_t breakInst = 0x91d02001;
- const static uint64_t lowBreakInst = breakInst;
- const static uint64_t highBreakInst = breakInst << 32;
- const static uint64_t breakWord = breakInst | (breakInst << 32);
- const static uint64_t lowMask = 0xFFFFFFFFULL;
- const static uint64_t highMask = lowMask << 32;
-
- /*
- * storage for the original contents of the child process's memory
- */
- uint64_t originalInst, originalAnnulInst;
-
- /*
- * Get information about where the process is and is headed next.
- */
- uint64_t currentPC = getRegVal(PC);
- bool unalignedPC = currentPC & 7;
- uint64_t alignedPC = currentPC & (~7);
- uint64_t nextPC = getRegVal(NPC);
- bool unalignedNPC = nextPC & 7;
- uint64_t alignedNPC = nextPC & (~7);
-
- //Get the current instruction
- uint64_t curInst = ptrace(PTRACE_PEEKTEXT, pid, alignedPC);
- curInst = unalignedPC ? (curInst & 0xffffffffULL) : (curInst >> 32);
-
- uint64_t bp1, bp2;
- int numTargets = getTargets(curInst, currentPC, nextPC, bp1, bp2);
- assert(numTargets == 1 || numTargets == 2);
-
- bool unalignedBp1 = bp1 & 7;
- uint64_t alignedBp1 = bp1 & (~7);
- bool unalignedBp2 = bp2 & 7;
- uint64_t alignedBp2 = bp2 & (~7);
- uint64_t origBp1, origBp2;
-
- /*
- * Set the first breakpoint
- */
- origBp1 = ptrace(PTRACE_PEEKTEXT, pid, alignedBp1, 0);
- uint64_t newBp1 = origBp1;
- newBp1 &= unalignedBp1 ? highMask : lowMask;
- newBp1 |= unalignedBp1 ? lowBreakInst : highBreakInst;
- if (ptrace(PTRACE_POKETEXT, pid, alignedBp1, newBp1) != 0)
- cerr << "Poke failed" << endl;
- /*
- * Set the second breakpoint if necessary
- */
- if (numTargets == 2) {
- origBp2 = ptrace(PTRACE_PEEKTEXT, pid, alignedBp2, 0);
- uint64_t newBp2 = origBp2;
- newBp2 &= unalignedBp2 ? highMask : lowMask;
- newBp2 |= unalignedBp2 ? lowBreakInst : highBreakInst;
- if (ptrace(PTRACE_POKETEXT, pid, alignedBp2, newBp2) != 0)
- cerr << "Poke failed" << endl;
- }
-
- /*
- * Restart the child process
- */
- //Note that the "addr" parameter is supposed to be ignored, but in at
- //least one version of the kernel, it must be 1 or it will set what
- //pc to continue from
- if (ptrace(PTRACE_CONT, pid, 1, 0) != 0)
- cerr << "Cont failed" << endl;
- doWait();
-
- /*
- * Update our record of the child's state
- */
- update(pid);
-
- /*
- * Put back the original contents of the childs address space in the
- * reverse order.
- */
- if (numTargets == 2) {
- if (ptrace(PTRACE_POKETEXT, pid, alignedBp2, origBp2) != 0)
- cerr << "Poke failed" << endl;
- }
- if (ptrace(PTRACE_POKETEXT, pid, alignedBp1, origBp1) != 0)
- cerr << "Poke failed" << endl;
-}
-
-int64_t
-SparcTraceChild::getRegVal(int num)
-{
- return getRegs(theregs, thefpregs, locals, inputs, num);
-}
-
-int64_t
-SparcTraceChild::getOldRegVal(int num)
-{
- return getRegs(oldregs, oldfpregs, oldLocals, oldInputs, num);
-}
-
-ostream &
-SparcTraceChild::outputStartState(ostream & os)
-{
- bool v8 = false;
- uint64_t sp = getSP();
- if (sp % 2) {
- os << "Detected a 64 bit executable.\n";
- v8 = false;
- } else {
- os << "Detected a 32 bit executable.\n";
- v8 = true;
- }
- uint64_t pc = getPC();
- char obuf[1024];
- sprintf(obuf, "Initial stack pointer = 0x%016llx\n", sp);
- os << obuf;
- sprintf(obuf, "Initial program counter = 0x%016llx\n", pc);
- os << obuf;
- if (!v8) {
- //Take out the stack bias
- sp += 2047;
- }
- //Output the window save area
- for (unsigned int x = 0; x < 16; x++) {
- uint64_t regspot = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
- if (v8) regspot = regspot >> 32;
- sprintf(obuf, "0x%016llx: Window save %d = 0x%016llx\n",
- sp, x+1, regspot);
- os << obuf;
- sp += v8 ? 4 : 8;
- }
- //Output the argument count
- uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
- if (v8) cargc = cargc >> 32;
- sprintf(obuf, "0x%016llx: Argc = 0x%016llx\n", sp, cargc);
- os << obuf;
- sp += v8 ? 4 : 8;
- //Output argv pointers
- int argCount = 0;
- uint64_t cargv;
- do {
- cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
- if (v8) cargv = cargv >> 32;
- sprintf(obuf, "0x%016llx: argv[%d] = 0x%016llx\n",
- sp, argCount++, cargv);
- os << obuf;
- sp += v8 ? 4 : 8;
- } while(cargv);
- //Output the envp pointers
- int envCount = 0;
- uint64_t cenvp;
- do {
- cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
- if (v8) cenvp = cenvp >> 32;
- sprintf(obuf, "0x%016llx: envp[%d] = 0x%016llx\n",
- sp, envCount++, cenvp);
- os << obuf;
- sp += v8 ? 4 : 8;
- } while (cenvp);
- uint64_t auxType, auxVal;
- do {
- auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
- if (v8) auxType = auxType >> 32;
- sp += (v8 ? 4 : 8);
- auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
- if (v8) auxVal = auxVal >> 32;
- sp += (v8 ? 4 : 8);
- sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n",
- sp - 8, auxType, auxVal);
- os << obuf;
- } while (auxType != 0 || auxVal != 0);
- //Print out the argument strings, environment strings, and file name.
- string current;
- uint64_t buf;
- uint64_t currentStart = sp;
- bool clearedInitialPadding = false;
- do {
- buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
- char * cbuf = (char *)&buf;
- for (int x = 0; x < sizeof(uint32_t); x++) {
- if (cbuf[x])
- current += cbuf[x];
- else {
- sprintf(obuf, "0x%016llx: \"%s\"\n",
- currentStart, current.c_str());
- os << obuf;
- current = "";
- currentStart = sp + x + 1;
- }
- }
- sp += (v8 ? 4 : 8);
- clearedInitialPadding = clearedInitialPadding || buf != 0;
- } while (!clearedInitialPadding || buf != 0);
- return os;
-}
-
-TraceChild *
-genTraceChild()
-{
- return new SparcTraceChild;
-}
-
+++ /dev/null
-/*
- * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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;
-}
-
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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