summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/m5/Makefile.alpha (renamed from util/m5/Makefile)2
-rw-r--r--util/m5/Makefile.sparc53
-rw-r--r--util/m5/m5.c33
-rw-r--r--util/m5/m5op.h2
-rw-r--r--util/m5/m5op_alpha.S (renamed from util/m5/m5op.S)23
-rw-r--r--util/m5/m5op_sparc.S153
-rw-r--r--util/m5/m5ops.h54
-rwxr-xr-xutil/regress8
-rw-r--r--util/statetrace/Makefile4
-rw-r--r--util/statetrace/arch/tracechild_sparc.cc259
-rw-r--r--util/statetrace/arch/tracechild_sparc.hh18
-rw-r--r--util/statetrace/statetrace.cc116
-rw-r--r--util/statetrace/tracechild.cc26
-rw-r--r--util/statetrace/tracechild.hh9
-rwxr-xr-xutil/tracediff10
15 files changed, 548 insertions, 222 deletions
diff --git a/util/m5/Makefile b/util/m5/Makefile.alpha
index a98092e47..e94c2901d 100644
--- a/util/m5/Makefile
+++ b/util/m5/Makefile.alpha
@@ -36,7 +36,7 @@ AS=$(CROSS_COMPILE)as
LD=$(CROSS_COMPILE)ld
CFLAGS=-O2
-OBJS=m5.o m5op.o
+OBJS=m5.o m5op_alpha.o
all: m5
diff --git a/util/m5/Makefile.sparc b/util/m5/Makefile.sparc
new file mode 100644
index 000000000..76d82857b
--- /dev/null
+++ b/util/m5/Makefile.sparc
@@ -0,0 +1,53 @@
+# Copyright (c) 2005-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: Nathan Binkert
+# Ali Saidi
+
+### If we are not compiling on an alpha, we must use cross tools ###
+ifneq ($(shell uname -m), sun4v)
+CROSS_COMPILE?=sparc64-sun-solaris2.10-
+endif
+CC=$(CROSS_COMPILE)gcc
+AS=$(CROSS_COMPILE)as
+LD=$(CROSS_COMPILE)ld
+
+CFLAGS=-O2 -m64
+OBJS=m5.o m5op_sparc.o
+
+all: m5
+
+%.o: %.S
+ $(CC) $(CFLAGS) -o $@ -c $<
+
+%.o: %.c
+ $(CC) $(CFLAGS) -o $@ -c $<
+
+m5: $(OBJS)
+ $(CC) -m64 -o $@ $(OBJS)
+
+clean:
+ rm -f *.o m5
diff --git a/util/m5/m5.c b/util/m5/m5.c
index ca555ed12..b103796a8 100644
--- a/util/m5/m5.c
+++ b/util/m5/m5.c
@@ -70,24 +70,6 @@ main(int argc, char *argv[])
command = argv[1];
- if (COMPARE("ivlb")) {
- if (argc != 3)
- usage();
-
- arg1 = strtoul(argv[2], NULL, 0);
- m5_ivlb(arg1);
- return 0;
- }
-
- if (COMPARE("ivle")) {
- if (argc != 3)
- usage();
-
- arg1 = strtoul(argv[2], NULL, 0);
- m5_ivle(arg1);
- return 0;
- }
-
if (COMPARE("initparam")) {
if (argc != 2)
usage();
@@ -203,21 +185,6 @@ main(int argc, char *argv[])
if (COMPARE("loadsymbol")) {
m5_loadsymbol(arg1);
return 0;
- if (COMPARE("readfile")) {
- char buf[256*1024];
- int offset = 0;
- int len;
-
- if (argc != 2)
- usage();
-
- while ((len = m5_readfile(buf, sizeof(buf), offset)) > 0) {
- write(STDOUT_FILENO, buf, len);
- offset += len;
- }
-
- return 0;
}
-
usage();
}
diff --git a/util/m5/m5op.h b/util/m5/m5op.h
index e8f2baaac..f4e6bb0f1 100644
--- a/util/m5/m5op.h
+++ b/util/m5/m5op.h
@@ -32,7 +32,7 @@
#ifndef __M5OP_H__
#define __M5OP_H__
-#include <asm/types.h>
+#include <stdint.h>
void arm(uint64_t address);
void quiesce(void);
diff --git a/util/m5/m5op.S b/util/m5/m5op_alpha.S
index 61e79d5d3..c5d0e65f8 100644
--- a/util/m5/m5op.S
+++ b/util/m5/m5op_alpha.S
@@ -31,28 +31,7 @@
#define m5_op 0x01
-#define arm_func 0x00
-#define quiesce_func 0x01
-#define quiescens_func 0x02
-#define quiescecycle_func 0x03
-#define quiescetime_func 0x04
-#define ivlb 0x10 // obsolete
-#define ivle 0x11 // obsolete
-#define exit_old_func 0x20 // deprecated!
-#define exit_func 0x21
-#define initparam_func 0x30
-#define loadsymbol_func 0x31
-#define resetstats_func 0x40
-#define dumpstats_func 0x41
-#define dumprststats_func 0x42
-#define ckpt_func 0x43
-#define readfile_func 0x50
-#define debugbreak_func 0x51
-#define switchcpu_func 0x52
-#define addsymbol_func 0x53
-#define panic_func 0x54
-#define anbegin_func 0x55
-#define anwait_func 0x56
+#include "m5ops.h"
#define INST(op, ra, rb, func) \
.long (((op) << 26) | ((ra) << 21) | ((rb) << 16) | (func))
diff --git a/util/m5/m5op_sparc.S b/util/m5/m5op_sparc.S
new file mode 100644
index 000000000..40248ff8b
--- /dev/null
+++ b/util/m5/m5op_sparc.S
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2003-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: Nathan Binkert
+ * Ali Saidi
+ */
+
+#define m5_op 0x2
+#define m5_op3 0x37
+
+#include "m5ops.h"
+
+#define INST(func, rs1, rs2, rd) \
+ .long (m5_op) << 30 | (rd) << 25 | (m5_op3) << 19 | (func) << 7 | \
+ (rs1) << 14 | (rs2) << 0;
+
+
+#define LEAF(func) \
+ .section ".text"; \
+ .align 4; \
+ .global func; \
+ .type func, #function; \
+func:
+
+#define END(func) \
+ .size func, (.-func)
+
+#define DEBUGBREAK INST(debugbreak_func, 0, 0, 0)
+#define M5EXIT INST(exit_func, 0, 0, 0)
+#define PANIC INST(panic_func, 0, 0, 0)
+#define READFILE INST(readfile_func, 0, 0, 0)
+
+LEAF(m5_exit)
+ retl
+ M5EXIT
+END(m5_exit)
+
+LEAF(m5_panic)
+ retl
+ PANIC
+END(m5_panic)
+
+LEAF(m5_readfile)
+ retl
+ READFILE
+END(m5_readfile)
+
+LEAF(m5_debugbreak)
+ retl
+ DEBUGBREAK
+END(m5_debugbreak)
+
+/* !!!!!! All code below here just panics !!!!!! */
+LEAF(arm)
+ retl
+ PANIC
+END(arm)
+
+LEAF(quiesce)
+ retl
+ PANIC
+END(quiesce)
+
+LEAF(quiesceNs)
+ retl
+ PANIC
+END(quiesceNs)
+
+LEAF(quiesceCycle)
+ retl
+ PANIC
+END(quiesceCycle)
+
+LEAF(quiesceTime)
+ retl
+ PANIC
+END(quiesceTime)
+
+LEAF(m5_initparam)
+ retl
+ PANIC
+END(m5_initparam)
+
+LEAF(m5_loadsymbol)
+ retl
+ PANIC
+END(m5_loadsymbol)
+
+LEAF(m5_reset_stats)
+ retl
+ PANIC
+END(m5_reset_stats)
+
+LEAF(m5_dump_stats)
+ retl
+ PANIC
+END(m5_dump_stats)
+
+LEAF(m5_dumpreset_stats)
+ retl
+ PANIC
+END(m5_dumpreset_stats)
+
+LEAF(m5_checkpoint)
+ retl
+ PANIC
+END(m5_checkpoint)
+
+LEAF(m5_switchcpu)
+ retl
+ PANIC
+END(m5_switchcpu)
+
+LEAF(m5_addsymbol)
+ retl
+ PANIC
+END(m5_addsymbol)
+
+LEAF(m5_anbegin)
+ retl
+ PANIC
+END(m5_anbegin)
+
+LEAF(m5_anwait)
+ retl
+ PANIC
+END(m5_anwait)
+
+
diff --git a/util/m5/m5ops.h b/util/m5/m5ops.h
new file mode 100644
index 000000000..ce0b39b29
--- /dev/null
+++ b/util/m5/m5ops.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2003-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: Nathan Binkert
+ * Ali Saidi
+ */
+
+#define arm_func 0x00
+#define quiesce_func 0x01
+#define quiescens_func 0x02
+#define quiescecycle_func 0x03
+#define quiescetime_func 0x04
+#define ivlb 0x10 // obsolete
+#define ivle 0x11 // obsolete
+#define exit_old_func 0x20 // deprecated!
+#define exit_func 0x21
+#define initparam_func 0x30
+#define loadsymbol_func 0x31
+#define resetstats_func 0x40
+#define dumpstats_func 0x41
+#define dumprststats_func 0x42
+#define ckpt_func 0x43
+#define readfile_func 0x50
+#define debugbreak_func 0x51
+#define switchcpu_func 0x52
+#define addsymbol_func 0x53
+#define panic_func 0x54
+#define anbegin_func 0x55
+#define anwait_func 0x56
+
diff --git a/util/regress b/util/regress
index 5d6f321f2..4d3eddab8 100755
--- a/util/regress
+++ b/util/regress
@@ -1,5 +1,5 @@
#! /usr/bin/env python
-# Copyright (c) 2005-2006 The Regents of The University of Michigan
+# Copyright (c) 2005-2007 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,7 @@ optparser.add_option('-v', '--verbose', dest='verbose', action='store_true',
default=False,
help='echo commands before executing')
optparser.add_option('--builds', dest='builds',
- default='ALPHA_SE,ALPHA_FS,MIPS_SE,SPARC_SE',
+ default='ALPHA_SE,ALPHA_FS,MIPS_SE,SPARC_SE,SPARC_FS',
help='comma-separated list of build targets to test '
" (default: '%default')" )
optparser.add_option('--variants', dest='variants',
@@ -86,6 +86,10 @@ try:
for build in builds
for variant in variants]
else:
+ # Ugly! Since we don't have any quick SPARC_FS tests remove the SPARC_FS target
+ # If we ever get a quick SPARC_FS test, this code should be removed
+ if 'quick' in tests and 'SPARC_FS' in builds:
+ builds.remove('SPARC_FS')
targets = ['build/%s/tests/%s/%s' % (build, variant, test)
for build in builds
for variant in variants
diff --git a/util/statetrace/Makefile b/util/statetrace/Makefile
index c59748163..2abc06d8e 100644
--- a/util/statetrace/Makefile
+++ b/util/statetrace/Makefile
@@ -1,4 +1,4 @@
-# Copyright (c) 2006 The Regents of The University of Michigan
+# 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
@@ -34,4 +34,4 @@ statetrace-native: statetrace.cc tracechild.cc tracechild_arch.cc printer.cc pri
g++ statetrace.cc tracechild.cc tracechild_arch.cc printer.cc -I ./ -I ./arch/ -O3 --static -o statetrace
statetrace-sparc: statetrace.cc tracechild.cc tracechild_arch.cc printer.cc printer.hh refcnt.hh regstate.hh tracechild.hh
- sparc64-unknown-linux-gnu-g++ statetrace.cc tracechild.cc tracechild_arch.cc printer.cc -I ./ -I ./arch/ -O3 --static -o statetrace
+ sparc64-unknown-linux-gnu-g++ statetrace.cc tracechild.cc tracechild_arch.cc printer.cc -g -I ./ -I ./arch/ -O3 --static -o statetrace
diff --git a/util/statetrace/arch/tracechild_sparc.cc b/util/statetrace/arch/tracechild_sparc.cc
index bad81b647..f60f9916b 100644
--- a/util/statetrace/arch/tracechild_sparc.cc
+++ b/util/statetrace/arch/tracechild_sparc.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 The Regents of The University of Michigan
+ * 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
@@ -54,8 +54,45 @@ string SparcTraceChild::regNames[numregs] = {
//Miscelaneous
"fsr", "fprs", "pc", "npc", "y", "cwp", "pstate", "asi", "ccr"};
+bool SparcTraceChild::sendState(int socket)
+{
+ uint64_t regVal = 0;
+ for(int x = 0; x <= I7; x++)
+ {
+ regVal = getRegVal(x);
+ if(write(socket, &regVal, sizeof(regVal)) == -1)
+ {
+ cerr << "Write failed! " << strerror(errno) << endl;
+ tracing = false;
+ return false;
+ }
+ }
+ regVal = getRegVal(PC);
+ if(write(socket, &regVal, sizeof(regVal)) == -1)
+ {
+ cerr << "Write failed! " << strerror(errno) << endl;
+ tracing = false;
+ return false;
+ }
+ regVal = getRegVal(NPC);
+ if(write(socket, &regVal, sizeof(regVal)) == -1)
+ {
+ cerr << "Write failed! " << strerror(errno) << endl;
+ tracing = false;
+ return false;
+ }
+ regVal = getRegVal(CCR);
+ if(write(socket, &regVal, sizeof(regVal)) == -1)
+ {
+ cerr << "Write failed! " << strerror(errno) << endl;
+ tracing = false;
+ return false;
+ }
+ return true;
+}
+
int64_t getRegs(regs & myregs, fpu & myfpu,
- int64_t * locals, int64_t * inputs, int num)
+ uint64_t * locals, uint64_t * inputs, int num)
{
assert(num < SparcTraceChild::numregs && num >= 0);
switch(num)
@@ -151,7 +188,6 @@ int64_t getRegs(regs & myregs, fpu & myfpu,
bool SparcTraceChild::update(int pid)
{
- static const int stackBias = 2047;
memcpy(&oldregs, &theregs, sizeof(regs));
memcpy(&oldfpregs, &thefpregs, sizeof(fpu));
memcpy(oldLocals, locals, 8 * sizeof(uint64_t));
@@ -161,13 +197,19 @@ bool SparcTraceChild::update(int pid)
cerr << "Update failed" << endl;
return false;
}
- uint64_t StackPointer = getRegVal(O6);
+ uint64_t stackPointer = getSP();
+ uint64_t stackBias = 2047;
+ bool v9 = stackPointer % 2;
for(unsigned int x = 0; x < 8; x++)
{
- locals[x] = ptrace(PTRACE_PEEKTEXT, pid,
- StackPointer + stackBias + x * 8, 0);
- inputs[x] = ptrace(PTRACE_PEEKTEXT, pid,
- StackPointer + stackBias + x * 8 + (8 * 8), 0);
+ 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;
@@ -182,8 +224,76 @@ SparcTraceChild::SparcTraceChild()
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
@@ -193,6 +303,8 @@ bool SparcTraceChild::step()
* 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;
@@ -212,60 +324,39 @@ bool SparcTraceChild::step()
bool unalignedNPC = nextPC & 7;
uint64_t alignedNPC = nextPC & (~7);
- /*
- * Store the original contents of the child process's memory
- */
- originalInst = ptrace(PTRACE_PEEKTEXT, pid, alignedNPC, 0);
- //Save a ptrace call if we can
- if(unalignedNPC)
- {
- originalAnnulInst = ptrace(PTRACE_PEEKTEXT, pid, alignedNPC+8, 0);
- }
+ //Get the current instruction
+ uint64_t curInst = ptrace(PTRACE_PEEKTEXT, pid, alignedPC);
+ curInst = unalignedPC ? (curInst & 0xffffffffULL) : (curInst >> 32);
- /*
- * Prepare breakpointed copies of child processes memory
- */
- uint64_t newInst, newAnnulInst;
- //If the current instruction is in the same word as the npc
- if(alignedPC == alignedNPC)
- {
- //Make sure we only replace the other part
- if(unalignedPC)
- newInst = (originalInst & lowMask) | (breakWord & highMask);
- else
- newInst = (originalInst & highMask) | (breakWord & lowMask);
- }
- else
- {
- //otherwise replace the whole thing
- newInst = breakWord;
- }
- //If the current instruction is in the same word as the word after
- //the npc
- if(alignedPC == alignedNPC+8)
- {
- //Make sure we only replace the other part
- if(unalignedPC)
- newAnnulInst = (originalAnnulInst & lowMask) | (breakWord & highMask);
- else
- newAnnulInst = (originalAnnulInst & highMask) | (breakWord & lowMask);
- }
- else
- {
- //otherwise replace the whole thing
- newAnnulInst = breakWord;
- }
+ 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;
/*
- * Stuff the breakpoint instructions into the child's address space.
+ * Set the first breakpoint
*/
- //Replace the word at npc
- if(ptrace(PTRACE_POKETEXT, pid, alignedNPC, newInst) != 0)
+ 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;
- //Replace the next word, if necessary
- if(unalignedNPC)
+ /*
+ * Set the second breakpoint if necessary
+ */
+ if(numTargets == 2)
{
- if(ptrace(PTRACE_POKETEXT, pid, alignedNPC+8, newAnnulInst) != 0)
+ 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;
}
@@ -285,16 +376,16 @@ bool SparcTraceChild::step()
update(pid);
/*
- * Put back the original contents of the childs address space
+ * Put back the original contents of the childs address space in the
+ * reverse order.
*/
- if(ptrace(PTRACE_POKETEXT, pid, alignedNPC, originalInst) != 0)
- cerr << "Repoke failed" << endl;
- if(unalignedNPC)
+ if(numTargets == 2)
{
- if(ptrace(PTRACE_POKETEXT, pid, alignedNPC+8, originalAnnulInst) != 0)
- cerr << "Repoke failed" << endl;
+ if(ptrace(PTRACE_POKETEXT, pid, alignedBp2, origBp2) != 0)
+ cerr << "Poke failed" << endl;
}
- return true;
+ if(ptrace(PTRACE_POKETEXT, pid, alignedBp1, origBp1) != 0)
+ cerr << "Poke failed" << endl;
}
int64_t SparcTraceChild::getRegVal(int num)
@@ -315,39 +406,56 @@ char * SparcTraceChild::printReg(int 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;
- //Take out the stack bias
- sp += 2047;
+ 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 += 8;
+ 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 += 8;
+ 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 += 8;
+ sp += v8 ? 4 : 8;
} while(cargv);
//Output the envp pointers
int envCount = 0;
@@ -355,20 +463,23 @@ ostream & SparcTraceChild::outputStartState(ostream & os)
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 += 8;
+ sp += v8 ? 4 : 8;
} while(cenvp);
uint64_t auxType, auxVal;
do
{
auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
- sp += 8;
+ if(v8) auxType = auxType >> 32;
+ sp += (v8 ? 4 : 8);
auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
- sp += 8;
+ if(v8) auxVal = auxVal >> 32;
+ sp += (v8 ? 4 : 8);
sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n",
- sp - 16, auxType, auxVal);
+ sp - 8, auxType, auxVal);
os << obuf;
} while(auxType != 0 || auxVal != 0);
//Print out the argument strings, environment strings, and file name.
@@ -380,7 +491,7 @@ ostream & SparcTraceChild::outputStartState(ostream & os)
{
buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
char * cbuf = (char *)&buf;
- for(int x = 0; x < sizeof(uint64_t); x++)
+ for(int x = 0; x < sizeof(uint32_t); x++)
{
if(cbuf[x])
current += cbuf[x];
@@ -393,7 +504,7 @@ ostream & SparcTraceChild::outputStartState(ostream & os)
currentStart = sp + x + 1;
}
}
- sp += 8;
+ sp += (v8 ? 4 : 8);
clearedInitialPadding = clearedInitialPadding || buf != 0;
} while(!clearedInitialPadding || buf != 0);
return os;
diff --git a/util/statetrace/arch/tracechild_sparc.hh b/util/statetrace/arch/tracechild_sparc.hh
index 80770211a..0284fb82e 100644
--- a/util/statetrace/arch/tracechild_sparc.hh
+++ b/util/statetrace/arch/tracechild_sparc.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 The Regents of The University of Michigan
+ * 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
@@ -72,18 +72,26 @@ private:
regs oldregs;
fpu thefpregs;
fpu oldfpregs;
- int64_t locals[8];
- int64_t oldLocals[8];
- int64_t inputs[8];
- int64_t oldInputs[8];
+ 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);
+
int getNumRegs()
{
return numregs;
diff --git a/util/statetrace/statetrace.cc b/util/statetrace/statetrace.cc
index 78fdf9393..4fe47dc02 100644
--- a/util/statetrace/statetrace.cc
+++ b/util/statetrace/statetrace.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 The Regents of The University of Michigan
+ * 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
@@ -35,88 +35,48 @@
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <unistd.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
-#include "tracechild.hh"
#include "printer.hh"
+#include "tracechild.hh"
using namespace std;
void printUsage(const char * execName)
{
- cout << execName << " -f <output format file> | -h | -r -- <command> <arguments>" << endl;
+ cout << execName << " -h | -r -- <command> <arguments>" << endl;
}
int main(int argc, char * argv[], char * envp[])
{
TraceChild * child = genTraceChild();
- NestingPrinter printer(child);
string args;
int startProgramArgs;
//Parse the command line arguments
- bool formatStringSet = false;
bool printInitial = false;
bool printTrace = true;
- string format;
for(int x = 1; x < argc; x++)
{
- if(!strcmp(argv[x], "-f"))
- {
- if(formatStringSet)
- {
- cerr << "Attempted to set format twice!"
- << endl;
- printUsage(argv[0]);
- return 1;
- }
- formatStringSet = true;
- x++;
- if(x >= argc)
- {
- cerr << "Incorrect usage.\n" << endl;
- printUsage(argv[0]);
- return 1;
- }
- ifstream formatFile(argv[x]);
- if(!formatFile)
- {
- cerr << "Problem opening file "
- << argv[x] << "." << endl;
- return 1;
- }
- format = "";
- while(formatFile)
- {
- string line;
- getline(formatFile, line);
- if(formatFile.eof())
- {
- format += line;
- break;
- }
- if(!formatFile)
- {
- cerr << "Problem reading from file "
- << argv[x] << "." << endl;
- return 1;
- }
- format += line + '\n';
- }
- }
- else if(!strcmp(argv[x], "-h"))
+ if(!strcmp(argv[x], "-h"))
{
printUsage(argv[0]);
return 0;
}
else if(!strcmp(argv[x], "-r"))
{
- cout << "Legal register names:" << endl;
- int numRegs = child->getNumRegs();
- for(unsigned int x = 0; x < numRegs; x++)
- {
- cout << "\t" << child->getRegName(x) << endl;
- }
- return 0;
+ cout << "Legal register names:" << endl;
+ int numRegs = child->getNumRegs();
+ for(unsigned int x = 0; x < numRegs; x++)
+ {
+ cout << "\t" << child->getRegName(x) << endl;
+ }
+ return 0;
}
else if(!strcmp(argv[x], "-i"))
{
@@ -145,9 +105,8 @@ int main(int argc, char * argv[], char * envp[])
return 1;
}
}
- for(unsigned int x = startProgramArgs; x < argc; x++)
- args += argv[x];
- if(!child->startTracing(argv[startProgramArgs], args.c_str()))
+ if(!child->startTracing(argv[startProgramArgs],
+ argv + startProgramArgs))
{
cerr << "Couldn't start target program" << endl;
return 1;
@@ -158,26 +117,41 @@ int main(int argc, char * argv[], char * envp[])
}
if(printTrace)
{
- if(!formatStringSet)
+ // Connect to m5
+ bool portSet = false;
+ int port;
+ int sock = socket(AF_INET, SOCK_STREAM, 0);
+ if(sock < 0)
{
- cerr << "No output format set!" << endl;
- child->stopTracing();
- printUsage(argv[0]);
- return 1;
+ cerr << "Error opening socket! " << strerror(errno) << endl;
+ return 1;
}
- if(!printer.configure(format))
+ struct hostent *server;
+ server = gethostbyname("zower.eecs.umich.edu");
+ if(!server)
{
- cerr << "Problem in the output format" << endl;
- child->stopTracing();
- return 1;
+ 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;
}
child->step();
while(child->isTracing())
{
- cout << printer;
+ if(!child->sendState(sock))
+ break;
child->step();
}
- cout << printer;
}
if(!child->stopTracing())
{
diff --git a/util/statetrace/tracechild.cc b/util/statetrace/tracechild.cc
index 292c45658..603429829 100644
--- a/util/statetrace/tracechild.cc
+++ b/util/statetrace/tracechild.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 The Regents of The University of Michigan
+ * 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
@@ -36,8 +36,9 @@
using namespace std;
-bool TraceChild::startTracing(const char * pathToFile, const char * arg)
+bool TraceChild::startTracing(const char * pathToFile, char * const argv[])
{
+ instructions = 0;
pid = fork();
if(pid == -1)
{
@@ -50,12 +51,23 @@ bool TraceChild::startTracing(const char * pathToFile, const char * arg)
//program to trace.
//Let our parent trace us
- ptrace(PTRACE_TRACEME, 0, 0, 0);
+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) == -1)
+ {
+ cout << "Failure calling TRACEME\n";
+ cout << 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
- execl(pathToFile, arg);
+ execve(pathToFile, argv, env);
//We should never get here, so this is an error!
+ cout << "Exec failed\n";
+ cout << strerror(errno) << endl;
return false;
}
@@ -121,6 +133,8 @@ bool TraceChild::doWait()
{
cerr << "Program exited! Exit status is "
<< WEXITSTATUS(wait_val) << endl;
+ cerr << "Executed " << instructions
+ << " instructions." << endl;
tracing = false;
return false;
}
@@ -132,6 +146,8 @@ bool TraceChild::doWait()
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)
@@ -139,6 +155,8 @@ bool TraceChild::doWait()
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
index f9c23b781..24712f816 100644
--- a/util/statetrace/tracechild.hh
+++ b/util/statetrace/tracechild.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 The Regents of The University of Michigan
+ * 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
@@ -37,11 +37,14 @@ class TraceChild : public RegState
{
protected:
int pid;
+ uint64_t instructions;
bool tracing;
public:
- TraceChild() : tracing(false)
+ TraceChild() : tracing(false), instructions(0)
{;}
- virtual bool startTracing(const char * pathToFile, const char * arg);
+ virtual bool sendState(int socket) = 0;
+ virtual bool startTracing(const char * pathToFile,
+ char * const argv[]);
virtual bool stopTracing();
virtual bool step();
virtual uint64_t getPC() = 0;
diff --git a/util/tracediff b/util/tracediff
index b25efe9b2..3633fdb48 100755
--- a/util/tracediff
+++ b/util/tracediff
@@ -1,5 +1,5 @@
#! /usr/bin/env perl
-# Copyright (c) 2003-2006 The Regents of The University of Michigan
+# Copyright (c) 2003-2007 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -60,6 +60,8 @@
# run only).
#
+use FindBin;
+
if (@ARGV < 2) {
die "Usage: tracediff \"sim1|sim2\" [common-arg \"arg1|arg2\" ...]\n";
}
@@ -101,9 +103,9 @@ mkdir($dir2) or die "Can't create dir $dir2\n";
$cmd1 = "$sim1 -d $dir1 $args1 2>&1 |";
$cmd2 = "$sim2 -d $dir2 $args2 2>&1 |";
-# This only works if you have rundiff in your path. I just edit it
-# with an explicit path if necessary.
-$fullcmd = "rundiff '$cmd1' '$cmd2' 2>&1 > tracediff-$$.out";
+# Expect that rundiff is in the same dir as the tracediff script.
+# FindBin figures that out for us.
+$fullcmd = "$FindBin::Bin/rundiff '$cmd1' '$cmd2' 2>&1 > tracediff-$$.out";
print "Executing $fullcmd\n";
system($fullcmd);