From 6835dbce340dcf5c651093229f2decd7f38943e6 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 27 Jul 2009 00:53:32 -0700 Subject: Statetrace: Fix up headers. --- util/statetrace/statetrace.cc | 16 ++++++++-------- util/statetrace/tracechild.cc | 7 ++++--- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'util') diff --git a/util/statetrace/statetrace.cc b/util/statetrace/statetrace.cc index 5f7224b25..824dfda69 100644 --- a/util/statetrace/statetrace.cc +++ b/util/statetrace/statetrace.cc @@ -28,19 +28,19 @@ * Authors: Gabe Black */ -#include +#include +#include #include +#include +#include +#include +#include #include +#include +#include #include #include -#include #include -#include -#include -#include -#include -#include -#include #include "printer.hh" #include "tracechild.hh" diff --git a/util/statetrace/tracechild.cc b/util/statetrace/tracechild.cc index 603429829..52e19a0e9 100644 --- a/util/statetrace/tracechild.cc +++ b/util/statetrace/tracechild.cc @@ -29,10 +29,11 @@ */ #include "tracechild.hh" -#include -#include -#include +#include #include +#include +#include +#include using namespace std; -- cgit v1.2.3 From 081b6fe9db97bf3d9e49428dc5e19f27b141a642 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Mon, 27 Jul 2009 00:53:39 -0700 Subject: ARM: Add ARM support to statetrace. --- util/statetrace/Makefile | 31 ++++- util/statetrace/arch/tracechild_arm.cc | 215 +++++++++++++++++++++++++++++++++ util/statetrace/arch/tracechild_arm.hh | 113 +++++++++++++++++ util/statetrace/tracechild_arch.cc | 2 + 4 files changed, 355 insertions(+), 6 deletions(-) create mode 100644 util/statetrace/arch/tracechild_arm.cc create mode 100644 util/statetrace/arch/tracechild_arm.hh (limited to 'util') 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..fc2eb3e24 --- /dev/null +++ b/util/statetrace/arch/tracechild_arm.cc @@ -0,0 +1,215 @@ +/* + * 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 "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++) + regDiffSinceUpdate[x] = false; +} + +bool ARMTraceChild::sendState(int socket) +{ + uint32_t regVal = 0; + for(int x = 0; x < numregs; x++) + { + regVal = getRegVal(x); + if(write(socket, ®Val, sizeof(regVal)) == -1) + { + cerr << "Write failed! " << strerror(errno) << endl; + tracing = false; + return false; + } + + } + + 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 = 0xE1200070; + const uint32_t bkpt_mask = 0xFFF000F0; + + const uint32_t swi_inst = 0x0F0000000; + const uint32_t swi_mask = 0x0F0000000; + + uint32_t next_op = ptrace(PTRACE_PEEKDATA, pid, getPC(), 0); + if ((next_op & swi_mask) == swi_inst) { + ptrace(PTRACE_POKEDATA, pid, next_op + sizeof(uint32_t), bkpt_inst); + ptraceSingleStep(); + ptrace(PTRACE_POKEDATA, pid, next_op + sizeof(uint32_t), next_op); + } + else + { + ptraceSingleStep(); + } +} + + +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 +#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: + 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/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__ || \ -- cgit v1.2.3 From 1ad4de252852941fdde1838f007daeb34d1885c3 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 27 Jul 2009 00:54:04 -0700 Subject: imported patch statetracehost.patch --- util/statetrace/statetrace.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'util') diff --git a/util/statetrace/statetrace.cc b/util/statetrace/statetrace.cc index 824dfda69..2861bb29c 100644 --- a/util/statetrace/statetrace.cc +++ b/util/statetrace/statetrace.cc @@ -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; @@ -127,7 +139,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; -- cgit v1.2.3 From 52b4a7c36ffbfcf48f6360ace5b69c18adddfa7a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 27 Jul 2009 00:54:30 -0700 Subject: ARM: Only send information that changed between statetrace and M5. --- util/statetrace/arch/tracechild_arm.cc | 29 ++++++++++++++++++++++------- util/statetrace/tracechild.cc | 5 ----- 2 files changed, 22 insertions(+), 12 deletions(-) (limited to 'util') diff --git a/util/statetrace/arch/tracechild_arm.cc b/util/statetrace/arch/tracechild_arm.cc index fc2eb3e24..4687b46f0 100644 --- a/util/statetrace/arch/tracechild_arm.cc +++ b/util/statetrace/arch/tracechild_arm.cc @@ -46,23 +46,38 @@ const char* ARMTraceChild::regNames[numregs] = { ARMTraceChild::ARMTraceChild() { - for (int x = 0; x < numregs; x++) + 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; - for(int x = 0; x < numregs; x++) - { - regVal = getRegVal(x); - if(write(socket, ®Val, sizeof(regVal)) == -1) - { + 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; diff --git a/util/statetrace/tracechild.cc b/util/statetrace/tracechild.cc index 52e19a0e9..85f42addd 100644 --- a/util/statetrace/tracechild.cc +++ b/util/statetrace/tracechild.cc @@ -79,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; } -- cgit v1.2.3 From 873112ea9924074212f1dd667d345850c6dce789 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 29 Jul 2009 00:14:43 -0700 Subject: ARM: Make sure the target process doesn't run away from statetrace. --- util/statetrace/arch/tracechild_arm.cc | 36 ++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'util') diff --git a/util/statetrace/arch/tracechild_arm.cc b/util/statetrace/arch/tracechild_arm.cc index 4687b46f0..b52c0694a 100644 --- a/util/statetrace/arch/tracechild_arm.cc +++ b/util/statetrace/arch/tracechild_arm.cc @@ -203,22 +203,28 @@ ostream & ARMTraceChild::outputStartState(ostream & os) bool ARMTraceChild::step() { + const uint32_t bkpt_inst = 0xe7f001f0; - const uint32_t bkpt_inst = 0xE1200070; - const uint32_t bkpt_mask = 0xFFF000F0; - - const uint32_t swi_inst = 0x0F0000000; - const uint32_t swi_mask = 0x0F0000000; - - uint32_t next_op = ptrace(PTRACE_PEEKDATA, pid, getPC(), 0); - if ((next_op & swi_mask) == swi_inst) { - ptrace(PTRACE_POKEDATA, pid, next_op + sizeof(uint32_t), bkpt_inst); - ptraceSingleStep(); - ptrace(PTRACE_POKEDATA, pid, next_op + sizeof(uint32_t), next_op); - } - else - { - ptraceSingleStep(); + 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); } } -- cgit v1.2.3 From e09ae149af4e97392a3ae7f8633c1bd18fe64e2d Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 29 Jul 2009 00:35:49 -0700 Subject: Statetrace: Make sure the current state is loaded to print the initial stack frame. The early call to child->step() was removed earlier because it confused the new differences-only protocol ARM sendState() was using. It's necessary that that gets called at least once before attempting to print the initial stack frame, though, because otherwise statetrace doesn't know what the stack pointer is. By putting the first call to child->step() in a common spot, both needs are met. --- util/statetrace/statetrace.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'util') diff --git a/util/statetrace/statetrace.cc b/util/statetrace/statetrace.cc index 2861bb29c..e2762ac2c 100644 --- a/util/statetrace/statetrace.cc +++ b/util/statetrace/statetrace.cc @@ -123,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); @@ -157,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)) -- cgit v1.2.3