From: Gabe Black Date: Thu, 3 Mar 2011 06:53:11 +0000 (-0800) Subject: Statetrace: Accomodate cross compiling statetrace with scons. X-Git-Tag: stable_2012_02_02~493 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=eab89a09d26fd39cdbb3ddd826465c8661403b89;p=gem5.git Statetrace: Accomodate cross compiling statetrace with scons. --HG-- rename : util/statetrace/arch/tracechild_amd64.cc => util/statetrace/arch/amd64/tracechild.cc rename : util/statetrace/arch/tracechild_amd64.hh => util/statetrace/arch/amd64/tracechild.hh rename : util/statetrace/arch/tracechild_arm.cc => util/statetrace/arch/arm/tracechild.cc rename : util/statetrace/arch/tracechild_arm.hh => util/statetrace/arch/arm/tracechild.hh rename : util/statetrace/arch/tracechild_i386.cc => util/statetrace/arch/i386/tracechild.cc rename : util/statetrace/arch/tracechild_i386.hh => util/statetrace/arch/i386/tracechild.hh rename : util/statetrace/arch/tracechild_sparc.cc => util/statetrace/arch/sparc/tracechild.cc rename : util/statetrace/arch/tracechild_sparc.hh => util/statetrace/arch/sparc/tracechild.hh rename : util/statetrace/tracechild_arch.cc => util/statetrace/base/arch_check.h rename : util/statetrace/regstate.hh => util/statetrace/base/regstate.hh rename : util/statetrace/statetrace.cc => util/statetrace/base/statetrace.cc rename : util/statetrace/tracechild.cc => util/statetrace/base/tracechild.cc rename : util/statetrace/tracechild.hh => util/statetrace/base/tracechild.hh --- diff --git a/util/statetrace/SConscript b/util/statetrace/SConscript new file mode 100644 index 000000000..7099b0a51 --- /dev/null +++ b/util/statetrace/SConscript @@ -0,0 +1,39 @@ +# Copyright (c) 2011 Gabe Black +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +import os + +Import('env', 'arch') + +env.Append(CPPPATH=Dir('.')) + +sources = [os.path.join('base', 'statetrace.cc'), + os.path.join('base', 'tracechild.cc'), + os.path.join('arch', arch, 'tracechild.cc')] +objects = [env.Object(source) for source in sources] +env.Program('statetrace', objects) diff --git a/util/statetrace/SConstruct b/util/statetrace/SConstruct index de0eade6a..2e93162d8 100644 --- a/util/statetrace/SConstruct +++ b/util/statetrace/SConstruct @@ -26,7 +26,42 @@ # # 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//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 +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// directories you specified on the command line. +''') + + +arches = 'amd64', 'arm', 'i386', 'sparc' + +import os + +main = Environment() +main.SetOption('duplicate', 'soft-copy') +main['CXXFLAGS'] = "-O3 -ggdb $_CPPINCFLAGS" + +main['CXX'] = ARGUMENTS.get('CXX', main['CXX']) + +for arch in arches: + env = main.Clone() + env['CXX'] = ARGUMENTS.get(arch.upper() + 'CXX', env['CXX']) + env.Append(CPPFLAGS = '-D__STATETRACE_%s__' % arch.upper()) + Export('env', 'arch') + env.SConscript('SConscript', variant_dir = os.path.join('build', arch)) diff --git a/util/statetrace/arch/amd64/tracechild.cc b/util/statetrace/arch/amd64/tracechild.cc new file mode 100644 index 000000000..5d3b660ab --- /dev/null +++ b/util/statetrace/arch/amd64/tracechild.cc @@ -0,0 +1,404 @@ +/* + * Copyright (c) 2007 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/util/statetrace/arch/amd64/tracechild.hh b/util/statetrace/arch/amd64/tracechild.hh new file mode 100644 index 000000000..6f28bc0bd --- /dev/null +++ b/util/statetrace/arch/amd64/tracechild.hh @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2007 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef REGSTATE_AMD64_HH +#define REGSTATE_AMD64_HH + +#include +#include +#include +#include +#include + +#include "base/tracechild.hh" + +class AMD64TraceChild : public TraceChild +{ + public: + enum RegNum + { + //GPRs + RAX, RCX, RDX, RBX, + //Base pointer and stack pointer + RSP, RBP, + //Index registers + RSI, RDI, + //New 64 bit mode registers + R8, R9, R10, R11, R12, R13, R14, R15, + //Segmentation registers + CS, DS, ES, FS, GS, SS, FS_BASE, GS_BASE, + //PC + RIP, + //Flags + EFLAGS, + //MMX + MMX0_0, MMX0_1, + MMX1_0, MMX1_1, + MMX2_0, MMX2_1, + MMX3_0, MMX3_1, + MMX4_0, MMX4_1, + MMX5_0, MMX5_1, + MMX6_0, MMX6_1, + MMX7_0, MMX7_1, + //XMM + XMM0_0, XMM0_1, XMM0_2, XMM0_3, + XMM1_0, XMM1_1, XMM1_2, XMM1_3, + XMM2_0, XMM2_1, XMM2_2, XMM2_3, + XMM3_0, XMM3_1, XMM3_2, XMM3_3, + XMM4_0, XMM4_1, XMM4_2, XMM4_3, + XMM5_0, XMM5_1, XMM5_2, XMM5_3, + XMM6_0, XMM6_1, XMM6_2, XMM6_3, + XMM7_0, XMM7_1, XMM7_2, XMM7_3, + XMM8_0, XMM8_1, XMM8_2, XMM8_3, + XMM9_0, XMM9_1, XMM9_2, XMM9_3, + XMM10_0, XMM10_1, XMM10_2, XMM10_3, + XMM11_0, XMM11_1, XMM11_2, XMM11_3, + XMM12_0, XMM12_1, XMM12_2, XMM12_3, + XMM13_0, XMM13_1, XMM13_2, XMM13_3, + XMM14_0, XMM14_1, XMM14_2, XMM14_3, + XMM15_0, XMM15_1, XMM15_2, XMM15_3, + numregs + }; + private: + int64_t getRegs(user_regs_struct & myregs, + user_fpregs_struct &myfpregs,int num); + user_regs_struct regs; + user_regs_struct oldregs; + user_fpregs_struct fpregs; + user_fpregs_struct oldfpregs; + bool regDiffSinceUpdate[numregs]; + + uint64_t findSyscall(); + + protected: + bool update(int pid); + + public: + + AMD64TraceChild(); + + bool sendState(int socket); + + int64_t getRegVal(int num); + int64_t getOldRegVal(int num); + uint64_t getPC() {return getRegVal(RIP);} + uint64_t getSP() {return getRegVal(RSP);} + std::ostream & outputStartState(std::ostream & output); + + bool step(); +}; + +#endif diff --git a/util/statetrace/arch/arm/tracechild.cc b/util/statetrace/arch/arm/tracechild.cc new file mode 100644 index 000000000..97b8d06ec --- /dev/null +++ b/util/statetrace/arch/arm/tracechild.cc @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2006-2009 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Gabe Black + */ + +#include +#include +#include +#include +#include + +#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 ... + // + // SUB PC, ... + // + // So we look for this pattern and set a breakpoint on the LR at the SUB + // instruction. + + + subsOp = ptrace(PTRACE_PEEKDATA, pid, pc, 0); + if ((subsOp & 0xFFFF0FFF) == 0xe3e00a0f) + foundMvn = true; + + if (foundMvn && ((subsOp & 0xFFF0F000) == 0xe240f000)) { + foundMvn = false; + lrOp = ptrace(PTRACE_PEEKDATA, pid, lr, 0); + ptrace(PTRACE_POKEDATA, pid, lr, bkpt_inst); + patch = true; + } + ptraceSingleStep(); + + if (patch) + ptrace(PTRACE_POKEDATA, pid, lr, lrOp); +} + + +TraceChild * +genTraceChild() +{ + return new ARMTraceChild; +} + diff --git a/util/statetrace/arch/arm/tracechild.hh b/util/statetrace/arch/arm/tracechild.hh new file mode 100644 index 000000000..f4e8ca694 --- /dev/null +++ b/util/statetrace/arch/arm/tracechild.hh @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2009 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Gabe Black + */ + +#ifndef TRACECHILD_ARM_HH +#define TRACECHILD_ARM_HH + +#include +#include +#include +#include +#include "base/tracechild.hh" + + +class ARMTraceChild : public TraceChild +{ + public: + enum RegNum + { + // r0 - r3 argument, temp, caller save + // r4 - r10 callee save + // r11 - FP + // r12 - temp + // r13 - stack + // r14 - link + // r15 - pc + R0, R1, R2, R3, R4, R5, R6, R7, + R8, R9, R10, FP, R12, SP, LR, PC, + CPSR, + numregs + }; + private: + uint32_t getRegs(user_regs& myregs, int num); + user_regs regs; + user_regs oldregs; + bool regDiffSinceUpdate[numregs]; + bool foundMvn; + + protected: + bool update(int pid); + + public: + ARMTraceChild(); + bool sendState(int socket); + + int64_t getRegVal(int num); + int64_t getOldRegVal(int num); + + bool step(); + + uint64_t + getPC() + { + return getRegVal(PC); + } + + uint64_t + getSP() + { + return getRegVal(SP); + } + + std::ostream & outputStartState(std::ostream & os); + +}; + +#endif + diff --git a/util/statetrace/arch/i386/tracechild.cc b/util/statetrace/arch/i386/tracechild.cc new file mode 100644 index 000000000..0d868767c --- /dev/null +++ b/util/statetrace/arch/i386/tracechild.cc @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include +#include +#include +#include + +#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; +} diff --git a/util/statetrace/arch/i386/tracechild.hh b/util/statetrace/arch/i386/tracechild.hh new file mode 100644 index 000000000..3af621ed6 --- /dev/null +++ b/util/statetrace/arch/i386/tracechild.hh @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef REGSTATE_I386_HH +#define REGSTATE_I386_HH + +#include +#include +#include +#include +#include + +#include "base/tracechild.hh" + +class I386TraceChild : public TraceChild +{ + public: + enum RegNum + { + //GPRs + EAX, EBX, ECX, EDX, + //Index registers + ESI, EDI, + //Base pointer and stack pointer + EBP, ESP, + //Segmentation registers + CS, DS, ES, FS, GS, SS, + //PC + EIP, + numregs + }; + private: + int64_t getRegs(user_regs_struct & myregs, int num); + user_regs_struct regs; + user_regs_struct oldregs; + bool regDiffSinceUpdate[numregs]; + + protected: + bool update(int pid); + + public: + + I386TraceChild(); + + int64_t getRegVal(int num); + int64_t getOldRegVal(int num); + uint64_t getPC() {return getRegVal(EIP);} + uint64_t getSP() {return getRegVal(ESP);} + std::ostream & + outputStartState(std::ostream & output) + { + output << "Printing i386 initial state not yet implemented" + << std::endl; + return output; + } +}; + +#endif diff --git a/util/statetrace/arch/sparc/tracechild.cc b/util/statetrace/arch/sparc/tracechild.cc new file mode 100644 index 000000000..b18739e24 --- /dev/null +++ b/util/statetrace/arch/sparc/tracechild.cc @@ -0,0 +1,472 @@ +/* + * Copyright (c) 2006-2007 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include +#include +#include +#include + +#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; +} + diff --git a/util/statetrace/arch/sparc/tracechild.hh b/util/statetrace/arch/sparc/tracechild.hh new file mode 100644 index 000000000..27670604a --- /dev/null +++ b/util/statetrace/arch/sparc/tracechild.hh @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2006-2007 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef TRACECHILD_SPARC_HH +#define TRACECHILD_SPARC_HH + +#include +#include +#include +#include +#include +#include +#include + +#include "base/tracechild.hh" + +struct regs; + +class SparcTraceChild : public TraceChild +{ + public: + enum RegNum + { + //Global registers + G0, G1, G2, G3, G4, G5, G6, G7, + //Output registers + O0, O1, O2, O3, O4, O5, O6, O7, + //Local registers + L0, L1, L2, L3, L4, L5, L6, L7, + //Input registers + I0, I1, I2, I3, I4, I5, I6, I7, + //Floating point + F0, F2, F4, F6, F8, F10, F12, F14, + F16, F18, F20, F22, F24, F26, F28, F30, + F32, F34, F36, F38, F40, F42, F44, F46, + F48, F50, F52, F54, F56, F58, F60, F62, + //Miscelaneous + FSR, FPRS, PC, NPC, Y, CWP, PSTATE, ASI, CCR, + numregs + }; + private: + regs theregs; + regs oldregs; + fpu thefpregs; + fpu oldfpregs; + uint64_t locals[8]; + uint64_t oldLocals[8]; + uint64_t inputs[8]; + uint64_t oldInputs[8]; + bool regDiffSinceUpdate[numregs]; + + //This calculates where the pc might go after the current instruction. + //while this equals npc for most instructions, it doesn't for all of + //them. The return value is the number of actual potential targets. + int getTargets(uint32_t inst, uint64_t pc, uint64_t npc, + uint64_t &target1, uint64_t &target2); + + protected: + bool update(int pid); + + public: + SparcTraceChild(); + + bool sendState(int socket); + + int64_t getRegVal(int num); + + int64_t getOldRegVal(int num); + + bool step(); + + uint64_t + getPC() + { + return getRegVal(PC); + } + + uint64_t + getSP() + { + return getRegVal(O6); + } + + std::ostream & outputStartState(std::ostream & os); +}; + +#endif diff --git a/util/statetrace/arch/tracechild_amd64.cc b/util/statetrace/arch/tracechild_amd64.cc deleted file mode 100644 index 780bb75a5..000000000 --- a/util/statetrace/arch/tracechild_amd64.cc +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright (c) 2007 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include -#include -#include -#include -#include -#include - -#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; -} diff --git a/util/statetrace/arch/tracechild_amd64.hh b/util/statetrace/arch/tracechild_amd64.hh deleted file mode 100644 index 256be5766..000000000 --- a/util/statetrace/arch/tracechild_amd64.hh +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2007 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#ifndef REGSTATE_AMD64_HH -#define REGSTATE_AMD64_HH - -#include -#include -#include -#include -#include - -#include "tracechild.hh" - -class AMD64TraceChild : public TraceChild -{ - public: - enum RegNum - { - //GPRs - RAX, RCX, RDX, RBX, - //Base pointer and stack pointer - RSP, RBP, - //Index registers - RSI, RDI, - //New 64 bit mode registers - R8, R9, R10, R11, R12, R13, R14, R15, - //Segmentation registers - CS, DS, ES, FS, GS, SS, FS_BASE, GS_BASE, - //PC - RIP, - //Flags - EFLAGS, - //MMX - MMX0_0, MMX0_1, - MMX1_0, MMX1_1, - MMX2_0, MMX2_1, - MMX3_0, MMX3_1, - MMX4_0, MMX4_1, - MMX5_0, MMX5_1, - MMX6_0, MMX6_1, - MMX7_0, MMX7_1, - //XMM - XMM0_0, XMM0_1, XMM0_2, XMM0_3, - XMM1_0, XMM1_1, XMM1_2, XMM1_3, - XMM2_0, XMM2_1, XMM2_2, XMM2_3, - XMM3_0, XMM3_1, XMM3_2, XMM3_3, - XMM4_0, XMM4_1, XMM4_2, XMM4_3, - XMM5_0, XMM5_1, XMM5_2, XMM5_3, - XMM6_0, XMM6_1, XMM6_2, XMM6_3, - XMM7_0, XMM7_1, XMM7_2, XMM7_3, - XMM8_0, XMM8_1, XMM8_2, XMM8_3, - XMM9_0, XMM9_1, XMM9_2, XMM9_3, - XMM10_0, XMM10_1, XMM10_2, XMM10_3, - XMM11_0, XMM11_1, XMM11_2, XMM11_3, - XMM12_0, XMM12_1, XMM12_2, XMM12_3, - XMM13_0, XMM13_1, XMM13_2, XMM13_3, - XMM14_0, XMM14_1, XMM14_2, XMM14_3, - XMM15_0, XMM15_1, XMM15_2, XMM15_3, - numregs - }; - private: - int64_t getRegs(user_regs_struct & myregs, - user_fpregs_struct &myfpregs,int num); - user_regs_struct regs; - user_regs_struct oldregs; - user_fpregs_struct fpregs; - user_fpregs_struct oldfpregs; - bool regDiffSinceUpdate[numregs]; - - uint64_t findSyscall(); - - protected: - bool update(int pid); - - public: - - AMD64TraceChild(); - - bool sendState(int socket); - - int64_t getRegVal(int num); - int64_t getOldRegVal(int num); - uint64_t getPC() {return getRegVal(RIP);} - uint64_t getSP() {return getRegVal(RSP);} - std::ostream & outputStartState(std::ostream & output); - - bool step(); -}; - -#endif diff --git a/util/statetrace/arch/tracechild_arm.cc b/util/statetrace/arch/tracechild_arm.cc deleted file mode 100644 index bd4f4bd36..000000000 --- a/util/statetrace/arch/tracechild_arm.cc +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2010 ARM Limited - * All rights reserved - * - * The license below extends only to copyright in the software and shall - * not be construed as granting a license to any other intellectual - * property including but not limited to intellectual property relating - * to a hardware implementation of the functionality of the software - * licensed hereunder. You may use the software subject to the license - * terms below provided that you ensure that this notice is replicated - * unmodified and in its entirety in all distributions of the software, - * modified or unmodified, in source code or in binary form. - * - * Copyright (c) 2006-2009 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Ali Saidi - * Gabe Black - */ - -#include -#include -#include -#include -#include - -#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 ... - // - // SUB PC, ... - // - // So we look for this pattern and set a breakpoint on the LR at the SUB - // instruction. - - - subsOp = ptrace(PTRACE_PEEKDATA, pid, pc, 0); - if ((subsOp & 0xFFFF0FFF) == 0xe3e00a0f) - foundMvn = true; - - if (foundMvn && ((subsOp & 0xFFF0F000) == 0xe240f000)) { - foundMvn = false; - lrOp = ptrace(PTRACE_PEEKDATA, pid, lr, 0); - ptrace(PTRACE_POKEDATA, pid, lr, bkpt_inst); - patch = true; - } - ptraceSingleStep(); - - if (patch) - ptrace(PTRACE_POKEDATA, pid, lr, lrOp); -} - - -TraceChild * -genTraceChild() -{ - return new ARMTraceChild; -} - diff --git a/util/statetrace/arch/tracechild_arm.hh b/util/statetrace/arch/tracechild_arm.hh deleted file mode 100644 index 0379885f1..000000000 --- a/util/statetrace/arch/tracechild_arm.hh +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2010 ARM Limited - * All rights reserved - * - * The license below extends only to copyright in the software and shall - * not be construed as granting a license to any other intellectual - * property including but not limited to intellectual property relating - * to a hardware implementation of the functionality of the software - * licensed hereunder. You may use the software subject to the license - * terms below provided that you ensure that this notice is replicated - * unmodified and in its entirety in all distributions of the software, - * modified or unmodified, in source code or in binary form. - * - * Copyright (c) 2009 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Ali Saidi - * Gabe Black - */ - -#ifndef TRACECHILD_ARM_HH -#define TRACECHILD_ARM_HH - -#include -#include -#include -#include -#include "tracechild.hh" - - -class ARMTraceChild : public TraceChild -{ - public: - enum RegNum - { - // r0 - r3 argument, temp, caller save - // r4 - r10 callee save - // r11 - FP - // r12 - temp - // r13 - stack - // r14 - link - // r15 - pc - R0, R1, R2, R3, R4, R5, R6, R7, - R8, R9, R10, FP, R12, SP, LR, PC, - CPSR, - numregs - }; - private: - uint32_t getRegs(user_regs& myregs, int num); - user_regs regs; - user_regs oldregs; - bool regDiffSinceUpdate[numregs]; - bool foundMvn; - - protected: - bool update(int pid); - - public: - ARMTraceChild(); - bool sendState(int socket); - - int64_t getRegVal(int num); - int64_t getOldRegVal(int num); - - bool step(); - - uint64_t - getPC() - { - return getRegVal(PC); - } - - uint64_t - getSP() - { - return getRegVal(SP); - } - - std::ostream & outputStartState(std::ostream & os); - -}; - -#endif - diff --git a/util/statetrace/arch/tracechild_i386.cc b/util/statetrace/arch/tracechild_i386.cc deleted file mode 100644 index 2cdeb29fa..000000000 --- a/util/statetrace/arch/tracechild_i386.cc +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include -#include -#include -#include - -#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; -} diff --git a/util/statetrace/arch/tracechild_i386.hh b/util/statetrace/arch/tracechild_i386.hh deleted file mode 100644 index 7f9f7499e..000000000 --- a/util/statetrace/arch/tracechild_i386.hh +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#ifndef REGSTATE_I386_HH -#define REGSTATE_I386_HH - -#include -#include -#include -#include -#include - -#include "tracechild.hh" - -class I386TraceChild : public TraceChild -{ - public: - enum RegNum - { - //GPRs - EAX, EBX, ECX, EDX, - //Index registers - ESI, EDI, - //Base pointer and stack pointer - EBP, ESP, - //Segmentation registers - CS, DS, ES, FS, GS, SS, - //PC - EIP, - numregs - }; - private: - int64_t getRegs(user_regs_struct & myregs, int num); - user_regs_struct regs; - user_regs_struct oldregs; - bool regDiffSinceUpdate[numregs]; - - protected: - bool update(int pid); - - public: - - I386TraceChild(); - - int64_t getRegVal(int num); - int64_t getOldRegVal(int num); - uint64_t getPC() {return getRegVal(EIP);} - uint64_t getSP() {return getRegVal(ESP);} - std::ostream & - outputStartState(std::ostream & output) - { - output << "Printing i386 initial state not yet implemented" - << std::endl; - return output; - } -}; - -#endif diff --git a/util/statetrace/arch/tracechild_sparc.cc b/util/statetrace/arch/tracechild_sparc.cc deleted file mode 100644 index dba8fa53d..000000000 --- a/util/statetrace/arch/tracechild_sparc.cc +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Copyright (c) 2006-2007 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include -#include -#include -#include - -#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; -} - diff --git a/util/statetrace/arch/tracechild_sparc.hh b/util/statetrace/arch/tracechild_sparc.hh deleted file mode 100644 index e479fce55..000000000 --- a/util/statetrace/arch/tracechild_sparc.hh +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2006-2007 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#ifndef TRACECHILD_SPARC_HH -#define TRACECHILD_SPARC_HH - -#include -#include -#include -#include -#include -#include -#include - -#include "tracechild.hh" - -struct regs; - -class SparcTraceChild : public TraceChild -{ - public: - enum RegNum - { - //Global registers - G0, G1, G2, G3, G4, G5, G6, G7, - //Output registers - O0, O1, O2, O3, O4, O5, O6, O7, - //Local registers - L0, L1, L2, L3, L4, L5, L6, L7, - //Input registers - I0, I1, I2, I3, I4, I5, I6, I7, - //Floating point - F0, F2, F4, F6, F8, F10, F12, F14, - F16, F18, F20, F22, F24, F26, F28, F30, - F32, F34, F36, F38, F40, F42, F44, F46, - F48, F50, F52, F54, F56, F58, F60, F62, - //Miscelaneous - FSR, FPRS, PC, NPC, Y, CWP, PSTATE, ASI, CCR, - numregs - }; - private: - regs theregs; - regs oldregs; - fpu thefpregs; - fpu oldfpregs; - uint64_t locals[8]; - uint64_t oldLocals[8]; - uint64_t inputs[8]; - uint64_t oldInputs[8]; - bool regDiffSinceUpdate[numregs]; - - //This calculates where the pc might go after the current instruction. - //while this equals npc for most instructions, it doesn't for all of - //them. The return value is the number of actual potential targets. - int getTargets(uint32_t inst, uint64_t pc, uint64_t npc, - uint64_t &target1, uint64_t &target2); - - protected: - bool update(int pid); - - public: - SparcTraceChild(); - - bool sendState(int socket); - - int64_t getRegVal(int num); - - int64_t getOldRegVal(int num); - - bool step(); - - uint64_t - getPC() - { - return getRegVal(PC); - } - - uint64_t - getSP() - { - return getRegVal(O6); - } - - std::ostream & outputStartState(std::ostream & os); -}; - -#endif diff --git a/util/statetrace/base/arch_check.h b/util/statetrace/base/arch_check.h new file mode 100644 index 000000000..db513a08e --- /dev/null +++ b/util/statetrace/base/arch_check.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2006-2007 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#if defined __STATETRACE_ALPHA__ + #if !defined __alpha__ + #error "Alpha toolchain required." + #endif +#elif defined __STATETRACE_AMD64__ + #if !defined __amd64__ + #error "Amd64 toolchain required." + #endif +#elif defined __STATETRACE_ARM__ + #if !defined __arm__ + #error "Arm toolchain required." + #endif +#elif defined __STATETRACE_HPPA__ + #if !defined __hppa__ + #error "Hppa toolchain required." + #endif +#elif defined __STATETRACE_I386__ + #if !(defined __i386__ || defined __i486__ || \ + defined __i586__ || defined __i686) + #error "I386 toolchain required." + #endif +#elif defined __STATETRACE_IA64__ + #if !defined __ia64__ + #error "IA64 toolchain required." + #endif +#elif defined __STATETRACE_MIPS__ + #if !defined __mips__ + #error "Mips toolchain required." + #endif +#elif defined __STATETRACE_POWERPC__ + #if !defined __powerpc__ + #error "PowerPC toolchain required." + #endif +#elif defined __STATETRACE_SPARC__ + #if !defined __sparc__ + #error "Sparc toolchain required." + #endif +#elif defined __STATETRACE_SH__ + #if !defined __sh__ + #error "SuperH toolchain required." + #endif +#elif defined __STATETRACE__S390__ + #if !defined __s390__ + #error "System/390 toolchain required." + #endif +#else + #error "Couldn't determine architecture." +#endif diff --git a/util/statetrace/base/regstate.hh b/util/statetrace/base/regstate.hh new file mode 100644 index 000000000..bab3485c6 --- /dev/null +++ b/util/statetrace/base/regstate.hh @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef REGSTATE_H +#define REGSTATE_H + +#include +#include + +class RegState +{ + protected: + virtual bool update(int pid) = 0; + public: + virtual int64_t getRegVal(int num) = 0; + virtual int64_t getOldRegVal(int num) = 0; +}; + +#endif diff --git a/util/statetrace/base/statetrace.cc b/util/statetrace/base/statetrace.cc new file mode 100644 index 000000000..c01147b86 --- /dev/null +++ b/util/statetrace/base/statetrace.cc @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2006-2007 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "base/arch_check.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tracechild.hh" + +using namespace std; + +void +printUsage(const char * execName) +{ + cout << execName << " -- " << endl; + cout << "options:" << endl; + cout << " -h print this help" << endl; + cout << " --host remote m5 host to connect to" << endl; + cout << " -i print initial stack state" << endl; + cout << " -nt don't print an instruction trace" << endl; +} + +int +main(int argc, char * argv[], char * envp[]) +{ + TraceChild * child = genTraceChild(); + string args; + int startProgramArgs; + + //Parse the command line arguments + bool printInitial = false; + bool printTrace = true; + string host = "localhost"; + + if (argc == 1) { + printUsage(argv[0]); + return 0; + } + for (int x = 1; x < argc; x++) { + if (!strcmp(argv[x], "-h")) { + printUsage(argv[0]); + return 0; + } + if (!strcmp(argv[x], "--host")) { + x++; + if (x >= argc) { + cerr << "Incorrect usage.\n" << endl; + printUsage(argv[0]); + return 1; + } + host = argv[x]; + } else if (!strcmp(argv[x], "-i")) { + printInitial = true; + } else if (!strcmp(argv[x], "-nt")) { + printTrace = false; + } else if (!strcmp(argv[x], "--")) { + x++; + if (x >= argc) { + cerr << "Incorrect usage.\n" << endl; + printUsage(argv[0]); + return 1; + } + startProgramArgs = x; + break; + } else { + cerr << "Incorrect usage.\n" << endl; + printUsage(argv[0]); + return 1; + } + } + if (!child->startTracing(argv[startProgramArgs], + argv + startProgramArgs)) { + cerr << "Couldn't start target program" << endl; + return 1; + } + child->step(); + if (printInitial) + child->outputStartState(cout); + if (printTrace) { + // Connect to m5 + bool portSet = false; + int port; + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + cerr << "Error opening socket! " << strerror(errno) << endl; + return 1; + } + struct hostent *server; + server = gethostbyname(host.c_str()); + if (!server) { + cerr << "Couldn't get host ip! " << strerror(errno) << endl; + return 1; + } + struct sockaddr_in serv_addr; + bzero((char *)&serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + bcopy((char *)server->h_addr, + (char *)&serv_addr.sin_addr.s_addr, + server->h_length); + serv_addr.sin_port = htons(8000); + if (connect(sock, (sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { + cerr << "Couldn't connect to server! " << strerror(errno) << endl; + return 1; + } + while (child->isTracing()) { + if (!child->sendState(sock)) + break; + child->step(); + } + } + if (!child->stopTracing()) { + cerr << "Couldn't stop child" << endl; + return 1; + } + return 0; +} + diff --git a/util/statetrace/base/tracechild.cc b/util/statetrace/base/tracechild.cc new file mode 100644 index 000000000..b5665ff37 --- /dev/null +++ b/util/statetrace/base/tracechild.cc @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2006-2007 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "tracechild.hh" +#include +#include +#include +#include +#include + +using namespace std; + +bool +TraceChild::startTracing(const char * pathToFile, char * const argv[]) +{ + instructions = 0; + pid = fork(); + if (pid == -1) { + cout << "fork failed" << endl; + return false; + } else if (pid == 0) { + //We're the child. Get things ready and then exec the program to trace. + //Let our parent trace us + if (ptrace(PTRACE_TRACEME, 0, 0, 0) == -1) { + cout << "Failure calling TRACEME\n" << strerror(errno) << endl; + return false; + } + + //Set up an empty environment for the child... We would want to + //specify this somehow at some point + char * env[] = {NULL}; + + //Start the program to trace + execve(pathToFile, argv, env); + + //We should never get here, so this is an error! + cout << "Exec failed\n" << strerror(errno) << endl; + return false; + } + + //From this point forward, we know we're in the parent process. + if (!doWait()) { + cout << "Didn't wait successfully" << endl; + return false; + } + tracing = true; + return true; +} + +bool +TraceChild::stopTracing() +{ + if (ptrace(PTRACE_KILL, pid, 0, 0) != 0) + return false; + tracing = false; + return true; +} + +bool +TraceChild::step() +{ + ptraceSingleStep(); +} + +bool +TraceChild::ptraceSingleStep() +{ + if (!tracing) { + cout << "Not tracing!" << endl; + return false; + } + if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0) != 0) { + switch (errno) { + case EBUSY: cout << "EBUSY" << endl; break; + case EFAULT: cout << "EFAULT" << endl; break; + case EIO: cout << "EIO" << endl; break; + case EPERM: cout << "EPERM" << endl; break; + case ESRCH: cout << "ESRCH" << endl; break; + default: cout << "Unknown error" << endl; break; + } + cout << "Not able to single step!" << endl; + tracing == false; + return false; + } + doWait(); + update(pid); +} + +bool +TraceChild::doWait() +{ + int wait_val; + wait(&wait_val); + if (WIFEXITED(wait_val)) { + cerr << "Program exited! Exit status is " + << WEXITSTATUS(wait_val) << endl; + cerr << "Executed " << instructions + << " instructions." << endl; + tracing = false; + return false; + } + if (WIFSIGNALED(wait_val)) { + if (WTERMSIG(wait_val)) + cerr << "Program terminated by signal " + << WTERMSIG(wait_val) << endl; + if (WCOREDUMP(wait_val)) + cerr << "Program core dumped!" << endl; + tracing = false; + cerr << "Executed " << instructions + << " instructions." << endl; + return false; + } + if (WIFSTOPPED(wait_val) && WSTOPSIG(wait_val) != SIGTRAP) { + cerr << "Program stopped by signal " << WSTOPSIG(wait_val) << endl; + tracing = false; + cerr << "Executed " << instructions << " instructions." << endl; + return false; + } + return true; +} diff --git a/util/statetrace/base/tracechild.hh b/util/statetrace/base/tracechild.hh new file mode 100644 index 000000000..bca04b414 --- /dev/null +++ b/util/statetrace/base/tracechild.hh @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2006-2007 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef TRACECHILD_HH +#define TRACECHILD_HH + +#include "base/regstate.hh" + +class TraceChild : public RegState +{ + protected: + int pid; + uint64_t instructions; + bool tracing; + public: + TraceChild() : tracing(false), instructions(0) + {;} + virtual bool sendState(int socket) = 0; + virtual bool startTracing(const char * pathToFile, char * const argv[]); + virtual bool stopTracing(); + virtual bool step(); + virtual std::ostream & outputStartState(std::ostream & os) = 0; + bool + isTracing() + { + return tracing; + } + protected: + bool ptraceSingleStep(); + bool doWait(); +}; + +TraceChild * genTraceChild(); + +#endif diff --git a/util/statetrace/regstate.hh b/util/statetrace/regstate.hh deleted file mode 100644 index bab3485c6..000000000 --- a/util/statetrace/regstate.hh +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#ifndef REGSTATE_H -#define REGSTATE_H - -#include -#include - -class RegState -{ - protected: - virtual bool update(int pid) = 0; - public: - virtual int64_t getRegVal(int num) = 0; - virtual int64_t getOldRegVal(int num) = 0; -}; - -#endif diff --git a/util/statetrace/statetrace.cc b/util/statetrace/statetrace.cc deleted file mode 100644 index ccc408fa7..000000000 --- a/util/statetrace/statetrace.cc +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2006-2007 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tracechild.hh" - -using namespace std; - -void -printUsage(const char * execName) -{ - cout << execName << " -- " << endl; - cout << "options:" << endl; - cout << " -h print this help" << endl; - cout << " --host remote m5 host to connect to" << endl; - cout << " -i print initial stack state" << endl; - cout << " -nt don't print an instruction trace" << endl; -} - -int -main(int argc, char * argv[], char * envp[]) -{ - TraceChild * child = genTraceChild(); - string args; - int startProgramArgs; - - //Parse the command line arguments - bool printInitial = false; - bool printTrace = true; - string host = "localhost"; - - if (argc == 1) { - printUsage(argv[0]); - return 0; - } - for (int x = 1; x < argc; x++) { - if (!strcmp(argv[x], "-h")) { - printUsage(argv[0]); - return 0; - } - if (!strcmp(argv[x], "--host")) { - x++; - if (x >= argc) { - cerr << "Incorrect usage.\n" << endl; - printUsage(argv[0]); - return 1; - } - host = argv[x]; - } else if (!strcmp(argv[x], "-i")) { - printInitial = true; - } else if (!strcmp(argv[x], "-nt")) { - printTrace = false; - } else if (!strcmp(argv[x], "--")) { - x++; - if (x >= argc) { - cerr << "Incorrect usage.\n" << endl; - printUsage(argv[0]); - return 1; - } - startProgramArgs = x; - break; - } else { - cerr << "Incorrect usage.\n" << endl; - printUsage(argv[0]); - return 1; - } - } - if (!child->startTracing(argv[startProgramArgs], - argv + startProgramArgs)) { - cerr << "Couldn't start target program" << endl; - return 1; - } - child->step(); - if (printInitial) - child->outputStartState(cout); - if (printTrace) { - // Connect to m5 - bool portSet = false; - int port; - int sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock < 0) { - cerr << "Error opening socket! " << strerror(errno) << endl; - return 1; - } - struct hostent *server; - server = gethostbyname(host.c_str()); - if (!server) { - cerr << "Couldn't get host ip! " << strerror(errno) << endl; - return 1; - } - struct sockaddr_in serv_addr; - bzero((char *)&serv_addr, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - bcopy((char *)server->h_addr, - (char *)&serv_addr.sin_addr.s_addr, - server->h_length); - serv_addr.sin_port = htons(8000); - if (connect(sock, (sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { - cerr << "Couldn't connect to server! " << strerror(errno) << endl; - return 1; - } - while (child->isTracing()) { - if (!child->sendState(sock)) - break; - child->step(); - } - } - if (!child->stopTracing()) { - cerr << "Couldn't stop child" << endl; - return 1; - } - return 0; -} - diff --git a/util/statetrace/tracechild.cc b/util/statetrace/tracechild.cc deleted file mode 100644 index b5665ff37..000000000 --- a/util/statetrace/tracechild.cc +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2006-2007 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include "tracechild.hh" -#include -#include -#include -#include -#include - -using namespace std; - -bool -TraceChild::startTracing(const char * pathToFile, char * const argv[]) -{ - instructions = 0; - pid = fork(); - if (pid == -1) { - cout << "fork failed" << endl; - return false; - } else if (pid == 0) { - //We're the child. Get things ready and then exec the program to trace. - //Let our parent trace us - if (ptrace(PTRACE_TRACEME, 0, 0, 0) == -1) { - cout << "Failure calling TRACEME\n" << strerror(errno) << endl; - return false; - } - - //Set up an empty environment for the child... We would want to - //specify this somehow at some point - char * env[] = {NULL}; - - //Start the program to trace - execve(pathToFile, argv, env); - - //We should never get here, so this is an error! - cout << "Exec failed\n" << strerror(errno) << endl; - return false; - } - - //From this point forward, we know we're in the parent process. - if (!doWait()) { - cout << "Didn't wait successfully" << endl; - return false; - } - tracing = true; - return true; -} - -bool -TraceChild::stopTracing() -{ - if (ptrace(PTRACE_KILL, pid, 0, 0) != 0) - return false; - tracing = false; - return true; -} - -bool -TraceChild::step() -{ - ptraceSingleStep(); -} - -bool -TraceChild::ptraceSingleStep() -{ - if (!tracing) { - cout << "Not tracing!" << endl; - return false; - } - if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0) != 0) { - switch (errno) { - case EBUSY: cout << "EBUSY" << endl; break; - case EFAULT: cout << "EFAULT" << endl; break; - case EIO: cout << "EIO" << endl; break; - case EPERM: cout << "EPERM" << endl; break; - case ESRCH: cout << "ESRCH" << endl; break; - default: cout << "Unknown error" << endl; break; - } - cout << "Not able to single step!" << endl; - tracing == false; - return false; - } - doWait(); - update(pid); -} - -bool -TraceChild::doWait() -{ - int wait_val; - wait(&wait_val); - if (WIFEXITED(wait_val)) { - cerr << "Program exited! Exit status is " - << WEXITSTATUS(wait_val) << endl; - cerr << "Executed " << instructions - << " instructions." << endl; - tracing = false; - return false; - } - if (WIFSIGNALED(wait_val)) { - if (WTERMSIG(wait_val)) - cerr << "Program terminated by signal " - << WTERMSIG(wait_val) << endl; - if (WCOREDUMP(wait_val)) - cerr << "Program core dumped!" << endl; - tracing = false; - cerr << "Executed " << instructions - << " instructions." << endl; - return false; - } - if (WIFSTOPPED(wait_val) && WSTOPSIG(wait_val) != SIGTRAP) { - cerr << "Program stopped by signal " << WSTOPSIG(wait_val) << endl; - tracing = false; - cerr << "Executed " << instructions << " instructions." << endl; - return false; - } - return true; -} diff --git a/util/statetrace/tracechild.hh b/util/statetrace/tracechild.hh deleted file mode 100644 index ad7e60e06..000000000 --- a/util/statetrace/tracechild.hh +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2006-2007 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#ifndef TRACECHILD_HH -#define TRACECHILD_HH - -#include "regstate.hh" - -class TraceChild : public RegState -{ - protected: - int pid; - uint64_t instructions; - bool tracing; - public: - TraceChild() : tracing(false), instructions(0) - {;} - virtual bool sendState(int socket) = 0; - virtual bool startTracing(const char * pathToFile, char * const argv[]); - virtual bool stopTracing(); - virtual bool step(); - virtual std::ostream & outputStartState(std::ostream & os) = 0; - bool - isTracing() - { - return tracing; - } - protected: - bool ptraceSingleStep(); - bool doWait(); -}; - -TraceChild * genTraceChild(); - -#endif diff --git a/util/statetrace/tracechild_arch.cc b/util/statetrace/tracechild_arch.cc deleted file mode 100644 index 052784df2..000000000 --- a/util/statetrace/tracechild_arch.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2006-2007 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#if defined __alpha__ - #error "Alpha architecture not implemented" -#elif defined __amd64__ - #include "arch/tracechild_amd64.cc" -#elif defined __arm__ - #include "arch/tracechild_arm.cc" -#elif defined __hppa__ - #error "Hppa architecture not implemented" -#elif defined __i386__ || defined __i486__ || \ - defined __i586__ || defined __i686 - #include "arch/tracechild_i386.cc" -#elif defined __ia64__ - #error "IA64 architecture not implemented" -#elif defined __mips__ - #error "Mips architecture not implemented" -#elif defined __powerpc__ - #error "PowerPC architecture not implemented" -#elif defined __sparc__ - #include "arch/tracechild_sparc.cc" -#elif defined __sh__ - #include "SuperH architecture not implemented" -#elif defined __s390__ - #include "System/390 architecture not implemented" -#else - #error "Couldn't determine architecture" -#endif