From 081b6fe9db97bf3d9e49428dc5e19f27b141a642 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Mon, 27 Jul 2009 00:53:39 -0700 Subject: [PATCH] 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 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__ || \