ARM: Fixup native trace support and add some v7/recent stack code
authorAli Saidi <Ali.Saidi@ARM.com>
Wed, 2 Jun 2010 17:58:17 +0000 (12:58 -0500)
committerAli Saidi <Ali.Saidi@ARM.com>
Wed, 2 Jun 2010 17:58:17 +0000 (12:58 -0500)
src/arch/arm/linux/process.cc
src/arch/arm/nativetrace.cc
src/arch/arm/process.cc
util/statetrace/arch/tracechild_arm.cc
util/statetrace/arch/tracechild_arm.hh
util/statetrace/statetrace.cc

index a5779d307ba392eb3da472555ccf11befa953fc2..32d9000200ac910c909006ee13f182c059ed7c91 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2010 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2003-2005 The Regents of The University of Michigan
  * Copyright (c) 2007-2008 The Florida State University
  * All rights reserved.
@@ -55,9 +67,9 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
 
     strcpy(name->sysname, "Linux");
     strcpy(name->nodename, "m5.eecs.umich.edu");
-    strcpy(name->release, "2.6.16.19");
+    strcpy(name->release, "2.6.29");
     strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
-    strcpy(name->machine, "arm");
+    strcpy(name->machine, "armv7l");
 
     name.copyOut(tc->getMemPort());
     return 0;
index 01f3205eb6cb3a616b813e6be52a153c4d464b18..e426d6611ff20b7bb7a3a2c0196c3f439a33ebcd 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2010 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2006 The Regents of The University of Michigan
  * All rights reserved.
  *
@@ -113,6 +125,14 @@ Trace::ArmNativeTrace::check(NativeTraceRecord *record)
     nState.update(this);
     mState.update(tc);
 
+    // If a syscall just happened native trace needs another tick
+    if ((mState.oldState[STATE_PC] == nState.oldState[STATE_PC]) &&
+            (mState.newState[STATE_PC] - 4 == nState.newState[STATE_PC])) {
+            DPRINTF(ExecRegDelta, "Advancing to match PCs after syscall\n");
+            nState.update(this);
+
+    }
+
     bool errorFound = false;
     // Regular int regs
     for (int i = 0; i < STATE_NUMVALS; i++) {
index 82e0a107f91d66402645a99d647cbea6fd5d7c43..00a6290c2c622cfeeab25aa04e09963a98b7fb62 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2010 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2007-2008 The Florida State University
  * All rights reserved.
  *
@@ -26,6 +38,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Stephen Hines
+ *          Ali Saidi
  */
 
 #include "arch/arm/isa_traits.hh"
@@ -118,7 +131,11 @@ ArmLiveProcess::argsInit(int intSize, int pageSize)
         Arm_Edsp = 1 << 7,
         Arm_Java = 1 << 8,
         Arm_Iwmmxt = 1 << 9,
-        Arm_Crunch = 1 << 10
+        Arm_Crunch = 1 << 10,
+        Arm_ThumbEE = 1 << 11,
+        Arm_Neon = 1 << 12,
+        Arm_Vfpv3 = 1 << 13,
+        Arm_Vfpv3d16 = 1 << 14
     };
 
     //Setup the auxilliary vectors. These will already have endian conversion.
@@ -134,9 +151,13 @@ ArmLiveProcess::argsInit(int intSize, int pageSize)
 //            Arm_Fpa |
             Arm_Vfp |
             Arm_Edsp |
-            Arm_Java |
+//            Arm_Java |
 //            Arm_Iwmmxt |
 //            Arm_Crunch |
+            Arm_ThumbEE |
+            Arm_Neon |
+            Arm_Vfpv3 |
+            Arm_Vfpv3d16 |
             0;
 
         //Bits which describe the system hardware capabilities
@@ -169,9 +190,13 @@ ArmLiveProcess::argsInit(int intSize, int pageSize)
         auxv.push_back(auxv_t(M5_AT_EGID, egid()));
         //Whether to enable "secure mode" in the executable
         auxv.push_back(auxv_t(M5_AT_SECURE, 0));
+
+        // Pointer to 16 bytes of random data
+        auxv.push_back(auxv_t(M5_AT_RANDOM, 0));
+
         //The filename of the program
         auxv.push_back(auxv_t(M5_AT_EXECFN, 0));
-        //The string "v51" with unknown meaning
+        //The string "v71" -- ARM v7 architecture
         auxv.push_back(auxv_t(M5_AT_PLATFORM, 0));
     }
 
@@ -180,9 +205,12 @@ ArmLiveProcess::argsInit(int intSize, int pageSize)
     // A sentry NULL void pointer at the top of the stack.
     int sentry_size = intSize;
 
-    string platform = "v51";
+    string platform = "v71";
     int platform_size = platform.size() + 1;
 
+    // Bytes for AT_RANDOM above, we'll just keep them 0
+    int aux_random_size = 16; // as per the specification
+
     // The aux vectors are put on the stack in two groups. The first group are
     // the vectors that are generated as the elf is loaded. The second group
     // are the ones that were computed ahead of time and include the platform
@@ -200,7 +228,7 @@ ArmLiveProcess::argsInit(int intSize, int pageSize)
 
     int info_block_size =
         sentry_size + env_data_size + arg_data_size +
-        aux_data_size + platform_size;
+        aux_data_size + platform_size + aux_random_size;
 
     //Each auxilliary vector is two 4 byte words
     int aux_array_size = intSize * 2 * (auxv.size() + 1);
@@ -240,7 +268,8 @@ ArmLiveProcess::argsInit(int intSize, int pageSize)
     uint32_t env_data_base = aux_data_base - env_data_size;
     uint32_t arg_data_base = env_data_base - arg_data_size;
     uint32_t platform_base = arg_data_base - platform_size;
-    uint32_t auxv_array_base = platform_base - aux_array_size - aux_padding;
+    uint32_t aux_random_base = platform_base - aux_random_size;
+    uint32_t auxv_array_base = aux_random_base - aux_array_size - aux_padding;
     uint32_t envp_array_base = auxv_array_base - envp_array_size;
     uint32_t argv_array_base = envp_array_base - argv_array_size;
     uint32_t argc_base = argv_array_base - argc_size;
@@ -249,6 +278,7 @@ ArmLiveProcess::argsInit(int intSize, int pageSize)
     DPRINTF(Stack, "0x%x - aux data\n", aux_data_base);
     DPRINTF(Stack, "0x%x - env data\n", env_data_base);
     DPRINTF(Stack, "0x%x - arg data\n", arg_data_base);
+    DPRINTF(Stack, "0x%x - random data\n", aux_random_base);
     DPRINTF(Stack, "0x%x - platform base\n", platform_base);
     DPRINTF(Stack, "0x%x - auxv array\n", auxv_array_base);
     DPRINTF(Stack, "0x%x - envp array\n", envp_array_base);
@@ -275,6 +305,9 @@ ArmLiveProcess::argsInit(int intSize, int pageSize)
         } else if (auxv[i].a_type == M5_AT_EXECFN) {
             auxv[i].a_val = aux_data_base;
             initVirtMem->writeString(aux_data_base, filename.c_str());
+        } else if (auxv[i].a_type == M5_AT_RANDOM) {
+            auxv[i].a_val = aux_random_base;
+            // Just leave the value 0, we don't want randomness
         }
     }
 
index b52c0694a94c0ae5d18d460712c7295a24c6bc47..b03cb208b399d7056e89700ae98372a3bf414844 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2010 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2006-2009 The Regents of The University of Michigan
  * All rights reserved.
  *
@@ -33,6 +45,7 @@
 #include <errno.h>
 #include <stdint.h>
 #include <cstring>
+#include <cstdio>
 
 #include "tracechild_arm.hh"
 
@@ -46,6 +59,8 @@ const char* ARMTraceChild::regNames[numregs] = {
 
 ARMTraceChild::ARMTraceChild()
 {
+    foundMvn = false;
+
     for (int x = 0; x < numregs; x++) {
         memset(&regs, 0, sizeof(regs));
         memset(&oldregs, 0, sizeof(regs));
@@ -79,7 +94,7 @@ bool ARMTraceChild::sendState(int socket)
         toSend -= sent;
         messagePtr += sent;
     }
-    
+
     return true;
 }
 
@@ -97,7 +112,7 @@ bool ARMTraceChild::update(int pid)
         cerr << "update: " << strerror(errno) << endl;
         return false;
     }
+
     for(unsigned int x = 0; x < numregs; x++)
         regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
     return true;
@@ -207,25 +222,39 @@ bool ARMTraceChild::step()
 
     uint32_t lr = getRegVal(14);
     uint32_t pc = getPC();
-    uint32_t lrOp;
+    uint32_t lrOp, subsOp;
+    char obuf[128];
+    bool patch = false;
 
     // 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.
+    // breakpoint there.
+    //
+    // Calls into the kernel user page always follow the form:
+    //  MVN ...
+    //  <possible MOV lr,...>
+    //  SUB PC, ...
+    //
+    //  So we look for this pattern and set a breakpoint on the LR at the SUB
+    //  instruction.
 
-    if (pc != lr) {
+
+    subsOp = ptrace(PTRACE_PEEKDATA, pid, pc, 0);
+    if ((subsOp & 0xFFFF0FFF) == 0xe3e00a0f)
+        foundMvn = true;
+
+    if (foundMvn && ((subsOp & 0xFFF0F000) == 0xe240f000)) {
+        foundMvn = false;
         lrOp = ptrace(PTRACE_PEEKDATA, pid, lr, 0);
         ptrace(PTRACE_POKEDATA, pid, lr, bkpt_inst);
+        patch = true;
     }
     ptraceSingleStep();
-    if (pc != lr) {
+
+    if (patch)
         ptrace(PTRACE_POKEDATA, pid, lr, lrOp);
-    }
 }
 
 
index 9e1af6a8d797184c67bf811b25167f532ac2fb86..79eccd891aa602e35708aae7e1c714ef71ac8136 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2010 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2009 The Regents of The University of Michigan
  * All rights reserved.
  *
@@ -63,15 +75,16 @@ class ARMTraceChild : public TraceChild
     user_regs regs;
     user_regs oldregs;
     bool regDiffSinceUpdate[numregs];
-    
+    bool foundMvn;
+
   protected:
     bool update(int pid);
-  
+
   public:
     ARMTraceChild();
     bool sendState(int socket);
 
-    int getNumRegs() 
+    int getNumRegs()
     {
         return numregs;
     }
@@ -90,7 +103,7 @@ class ARMTraceChild : public TraceChild
 
     int64_t getRegVal(int num);
     int64_t getOldRegVal(int num);
-  
+
     bool step();
 
     uint64_t getPC()
index e2762ac2c7a9e5920327c404bd644d5ca027ac7c..d50c24f5927522082384d0d734955fcd59754bb5 100644 (file)
@@ -49,7 +49,13 @@ using namespace std;
 
 void printUsage(const char * execName)
 {
-    cout << execName << " -h | -r -- <command> <arguments>" << endl;
+    cout << execName << " <options> -- <command> <arguments>" << endl;
+    cout << "options:" << endl;
+    cout << "         -h          print this help" << endl;
+    cout << "         --host      remote m5 host to connect to" << endl;
+    cout << "         -r          print register names" << endl;
+    cout << "         -i          print initial stack state" << endl;
+    cout << "         -nt         don't print an instruction trace" << endl;
 }
 
 int main(int argc, char * argv[], char * envp[])
@@ -62,6 +68,11 @@ int main(int argc, char * argv[], char * envp[])
     bool printInitial = false;
     bool printTrace = true;
     string host = "localhost";
+
+    if (argc == 1) {
+        printUsage(argv[0]);
+        return 0;
+    }
     for(int x = 1; x < argc; x++)
     {
         if(!strcmp(argv[x], "-h"))