ARM: Add ARM support to statetrace.
authorAli Saidi <saidi@eecs.umich.edu>
Mon, 27 Jul 2009 07:53:39 +0000 (00:53 -0700)
committerAli Saidi <saidi@eecs.umich.edu>
Mon, 27 Jul 2009 07:53:39 +0000 (00:53 -0700)
util/statetrace/Makefile
util/statetrace/arch/tracechild_arm.cc [new file with mode: 0644]
util/statetrace/arch/tracechild_arm.hh [new file with mode: 0644]
util/statetrace/tracechild_arch.cc

index 2abc06d8ebc452f158b8c50cd3b3a6f1b2cb23a4..438828981d9a300e868e3f00e661308e8cf2cffb 100644 (file)
 #
 # 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 (file)
index 0000000..fc2eb3e
--- /dev/null
@@ -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 <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++)
+        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, &regVal, 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, &regs) != 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 (file)
index 0000000..9e1af6a
--- /dev/null
@@ -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
+
index 570a12b5432a9fdec27ec621d130b1aaa0b521c1..345de46e8d6866377fc37f13ffe70e1f3d9471ea 100644 (file)
@@ -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__ || \