diff options
author | Korey Sewell <ksewell@umich.edu> | 2009-07-31 10:40:42 -0400 |
---|---|---|
committer | Korey Sewell <ksewell@umich.edu> | 2009-07-31 10:40:42 -0400 |
commit | aa75b9a7a7489bf86c4e6d406ff612e596ddff96 (patch) | |
tree | 58a6816583a21c19c181e32bff10bf74aa9ad15f /util | |
parent | 60063cc700912666fa8b7968d692d00a1e82cb67 (diff) | |
parent | 3dd3de5feb31055a48acb39575da25a9cea2626d (diff) | |
download | gem5-aa75b9a7a7489bf86c4e6d406ff612e596ddff96.tar.xz |
merge mips fix and statetrace changes
Diffstat (limited to 'util')
-rw-r--r-- | util/statetrace/Makefile | 31 | ||||
-rw-r--r-- | util/statetrace/arch/tracechild_arm.cc | 236 | ||||
-rw-r--r-- | util/statetrace/arch/tracechild_arm.hh | 113 | ||||
-rw-r--r-- | util/statetrace/statetrace.cc | 32 | ||||
-rw-r--r-- | util/statetrace/tracechild.cc | 12 | ||||
-rw-r--r-- | util/statetrace/tracechild_arch.cc | 2 |
6 files changed, 402 insertions, 24 deletions
diff --git a/util/statetrace/Makefile b/util/statetrace/Makefile index 2abc06d8e..438828981 100644 --- a/util/statetrace/Makefile +++ b/util/statetrace/Makefile @@ -26,12 +26,31 @@ # # Authors: Gabe Black -.PHONY: statetrace +CXX := g++ +INCLUDES := -I ./ -I ./arch +CXXFLAGS := -O3 -ggdb -statetrace: statetrace-native +define build-obj +$(CXX) -c $(patsubst %.o,%.cc,$@) -o $@ $(INCLUDES) $(CXXFLAGS) +endef -statetrace-native: statetrace.cc tracechild.cc tracechild_arch.cc printer.cc printer.hh refcnt.hh regstate.hh tracechild.hh - g++ statetrace.cc tracechild.cc tracechild_arch.cc printer.cc -I ./ -I ./arch/ -O3 --static -o statetrace +define final-link +$(CXX) $(INCLUDES) $(CXXFLAGS) -o $@ $^ +endef -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 -g -I ./ -I ./arch/ -O3 --static -o statetrace +all: statetrace + +printer.o: printer.cc printer.hh tracechild.hh refcnt.hh regstate.hh + $(build-obj) +statetrace.o: statetrace.cc printer.hh tracechild.hh refcnt.hh regstate.hh + $(build-obj) +tracechild.o: tracechild.cc tracechild.hh regstate.hh + $(build-obj) +tracechild_arch.o: statetrace.cc printer.hh tracechild.hh refcnt.hh regstate.hh arch/tracechild_arm.hh arch/tracechild_arm.cc arch/tracechild_i386.hh arch/tracechild_i386.cc arch/tracechild_amd64.cc arch/tracechild_amd64.hh arch/tracechild_sparc.cc arch/tracechild_sparc.hh + $(build-obj) + +statetrace: printer.o statetrace.o tracechild.o tracechild_arch.o + $(final-link) + +clean: + rm -f *.o statetrace diff --git a/util/statetrace/arch/tracechild_arm.cc b/util/statetrace/arch/tracechild_arm.cc new file mode 100644 index 000000000..b52c0694a --- /dev/null +++ b/util/statetrace/arch/tracechild_arm.cc @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2006-2009 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Gabe Black + */ + +#include <iostream> +#include <errno.h> +#include <stdint.h> +#include <cstring> + +#include "tracechild_arm.hh" + +using namespace std; + +const char* ARMTraceChild::regNames[numregs] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "fp", "r12", "sp", "lr", "pc", + "cpsr" }; + + +ARMTraceChild::ARMTraceChild() +{ + 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); +} + +char * ARMTraceChild::printReg(int num) +{ + sprintf(printBuffer, "0x%08X", (uint32_t)getRegVal(num)); + return printBuffer; +} + +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; + + // 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. If the lr happens to point to the next instruction + // we'll leave out our breakpoint to avoid an infinite loop. This isn't a + // fool proof strategy, but it should work well in all the reasonable + // scenarios I can think of right now. + + if (pc != lr) { + lrOp = ptrace(PTRACE_PEEKDATA, pid, lr, 0); + ptrace(PTRACE_POKEDATA, pid, lr, bkpt_inst); + } + ptraceSingleStep(); + if (pc != lr) { + 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 new file mode 100644 index 000000000..9e1af6a8d --- /dev/null +++ b/util/statetrace/arch/tracechild_arm.hh @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2009 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Gabe Black + */ + +#ifndef TRACECHILD_ARM_HH +#define TRACECHILD_ARM_HH + +#include <cassert> +#include <string> +#include <sys/user.h> +#include <sys/ptrace.h> +#include "tracechild.hh" + + +class ARMTraceChild : public TraceChild +{ + public: + enum RegNum + { + // r0 - r3 argument, temp, caller save + // r4 - r10 callee save + // r11 - FP + // r12 - temp + // r13 - stack + // r14 - link + // r15 - pc + R0, R1, R2, R3, R4, R5, R6, R7, + R8, R9, R10, FP, R12, SP, LR, PC, + CPSR, + numregs + }; + private: + char printBuffer[256]; + static const char *regNames[numregs]; + uint32_t getRegs(user_regs& myregs, int num); + user_regs regs; + user_regs oldregs; + bool regDiffSinceUpdate[numregs]; + + protected: + bool update(int pid); + + public: + ARMTraceChild(); + bool sendState(int socket); + + int getNumRegs() + { + return numregs; + } + + bool diffSinceUpdate(int num) + { + assert(num < numregs && num >= 0); + return regDiffSinceUpdate[num]; + } + + std::string getRegName(int num) + { + assert(num < numregs && num >= 0); + return regNames[num]; + } + + int64_t getRegVal(int num); + int64_t getOldRegVal(int num); + + bool step(); + + uint64_t getPC() + { + return getRegVal(PC); + } + + uint64_t getSP() + { + return getRegVal(SP); + } + + char * printReg(int num); + + std::ostream & outputStartState(std::ostream & os); + +}; + +#endif + diff --git a/util/statetrace/statetrace.cc b/util/statetrace/statetrace.cc index 5f7224b25..e2762ac2c 100644 --- a/util/statetrace/statetrace.cc +++ b/util/statetrace/statetrace.cc @@ -28,19 +28,19 @@ * Authors: Gabe Black */ -#include <iostream> +#include <cstring> +#include <errno.h> #include <fstream> +#include <iostream> +#include <netdb.h> +#include <netinet/in.h> +#include <stdio.h> #include <string> +#include <sys/ptrace.h> +#include <sys/socket.h> #include <sys/types.h> #include <sys/wait.h> -#include <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 "printer.hh" #include "tracechild.hh" @@ -61,6 +61,7 @@ int main(int argc, char * argv[], char * envp[]) //Parse the command line arguments bool printInitial = false; bool printTrace = true; + string host = "localhost"; for(int x = 1; x < argc; x++) { if(!strcmp(argv[x], "-h")) @@ -68,6 +69,17 @@ int main(int argc, char * argv[], char * envp[]) 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], "-r")) { cout << "Legal register names:" << endl; @@ -111,6 +123,7 @@ int main(int argc, char * argv[], char * envp[]) cerr << "Couldn't start target program" << endl; return 1; } + child->step(); if(printInitial) { child->outputStartState(cout); @@ -127,7 +140,7 @@ int main(int argc, char * argv[], char * envp[]) return 1; } struct hostent *server; - server = gethostbyname("localhost"); + server = gethostbyname(host.c_str()); if(!server) { cerr << "Couldn't get host ip! " << strerror(errno) << endl; @@ -145,7 +158,6 @@ int main(int argc, char * argv[], char * envp[]) cerr << "Couldn't connect to server! " << strerror(errno) << endl; return 1; } - child->step(); while(child->isTracing()) { if(!child->sendState(sock)) diff --git a/util/statetrace/tracechild.cc b/util/statetrace/tracechild.cc index 603429829..85f42addd 100644 --- a/util/statetrace/tracechild.cc +++ b/util/statetrace/tracechild.cc @@ -29,10 +29,11 @@ */ #include "tracechild.hh" -#include <sys/wait.h> -#include <sys/ptrace.h> -#include <iostream> +#include <cstring> #include <errno.h> +#include <iostream> +#include <sys/ptrace.h> +#include <sys/wait.h> using namespace std; @@ -78,11 +79,6 @@ bool TraceChild::startTracing(const char * pathToFile, char * const argv[]) return false; } tracing = true; - if(!update(pid)) - { - cout << "Didn't update successfully!" << endl; - return false; - } return true; } diff --git a/util/statetrace/tracechild_arch.cc b/util/statetrace/tracechild_arch.cc index 570a12b54..345de46e8 100644 --- a/util/statetrace/tracechild_arch.cc +++ b/util/statetrace/tracechild_arch.cc @@ -33,6 +33,8 @@ #elif defined __amd64__ // #error "AMD64 architecture not implemented" #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__ || \ |