diff options
Diffstat (limited to 'util')
-rw-r--r-- | util/m5/Makefile.alpha (renamed from util/m5/Makefile) | 2 | ||||
-rw-r--r-- | util/m5/Makefile.sparc | 53 | ||||
-rw-r--r-- | util/m5/m5.c | 33 | ||||
-rw-r--r-- | util/m5/m5op.h | 2 | ||||
-rw-r--r-- | util/m5/m5op_alpha.S (renamed from util/m5/m5op.S) | 23 | ||||
-rw-r--r-- | util/m5/m5op_sparc.S | 153 | ||||
-rw-r--r-- | util/m5/m5ops.h | 54 | ||||
-rwxr-xr-x | util/regress | 8 | ||||
-rw-r--r-- | util/statetrace/Makefile | 4 | ||||
-rw-r--r-- | util/statetrace/arch/tracechild_sparc.cc | 259 | ||||
-rw-r--r-- | util/statetrace/arch/tracechild_sparc.hh | 18 | ||||
-rw-r--r-- | util/statetrace/statetrace.cc | 116 | ||||
-rw-r--r-- | util/statetrace/tracechild.cc | 26 | ||||
-rw-r--r-- | util/statetrace/tracechild.hh | 9 | ||||
-rwxr-xr-x | util/tracediff | 10 |
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, ®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, - 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); |