Merge from branches/ARM, all parts of the ARM-Linux port except for
the changes to do with reading and using ELF and DWARF3 info.
This breaks all targets except amd64-linux and x86-linux.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10982 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_libcassert.c b/coregrind/m_libcassert.c
index bfab45c..d2770cd 100644
--- a/coregrind/m_libcassert.c
+++ b/coregrind/m_libcassert.c
@@ -45,51 +45,94 @@
    Assertery.
    ------------------------------------------------------------------ */
 
-#if defined(VGP_x86_linux)  ||  defined(VGP_x86_darwin)
-#  define GET_REAL_PC_SP_AND_FP(pc, sp, fp)      \
-      asm("call 0f;" \
-          "0: popl %0;" \
-          "movl %%esp, %1;" \
-          "movl %%ebp, %2;" \
-          : "=r" (pc),\
-            "=r" (sp),\
-            "=r" (fp));
-#elif defined(VGP_amd64_linux)  ||  defined(VGP_amd64_darwin)
-#  define GET_REAL_PC_SP_AND_FP(pc, sp, fp)      \
-      asm("leaq 0(%%rip), %0;" \
-          "movq %%rsp, %1;" \
-          "movq %%rbp, %2;" \
-          : "=r" (pc),\
-            "=r" (sp),\
-            "=r" (fp));
+#if defined(VGP_x86_linux) || defined(VGP_x86_darwin)
+#  define GET_STARTREGS(srP)                              \
+      { UInt eip, esp, ebp;                               \
+        __asm__ __volatile__(                             \
+           "call 0f;"                                     \
+           "0: popl %0;"                                  \
+           "movl %%esp, %1;"                              \
+           "movl %%ebp, %2;"                              \
+           : "=r" (eip), "=r" (esp), "=r" (ebp)           \
+           : /* reads none */                             \
+           : "memory"                                     \
+        );                                                \
+        (srP)->r_pc = (ULong)eip;                         \
+        (srP)->r_sp = (ULong)esp;                         \
+        (srP)->misc.X86.r_ebp = ebp;                      \
+      }
+#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin)
+#  define GET_STARTREGS(srP)                              \
+      { ULong rip, rsp, rbp;                              \
+        __asm__ __volatile__(                             \
+           "leaq 0(%%rip), %0;"                           \
+           "movq %%rsp, %1;"                              \
+           "movq %%rbp, %2;"                              \
+           : "=r" (rip), "=r" (rsp), "=r" (rbp)           \
+           : /* reads none */                             \
+           : "memory"                                     \
+        );                                                \
+        (srP)->r_pc = rip;                                \
+        (srP)->r_sp = rsp;                                \
+        (srP)->misc.AMD64.r_rbp = rbp;                    \
+      }
 #elif defined(VGP_ppc32_linux) || defined(VGP_ppc32_aix5)
-#  define GET_REAL_PC_SP_AND_FP(pc, sp, fp)                   \
-      asm("mflr 0;"                   /* r0 = lr */           \
-          "bl m_libcassert_get_ip;"   /* lr = pc */           \
-          "m_libcassert_get_ip:\n"                            \
-          "mflr %0;"                \
-          "mtlr 0;"                   /* restore lr */        \
-          "mr %1,1;"                \
-          "mr %2,1;"                \
-          : "=r" (pc),              \
-            "=r" (sp),              \
-            "=r" (fp)               \
-          : /* reads none */        \
-          : "r0" /* trashed */ );
+#  define GET_STARTREGS(srP)                              \
+      { UInt cia, r1, lr;                                 \
+        __asm__ __volatile__(                             \
+           "mflr 0;"                   /* r0 = lr */      \
+           "bl m_libcassert_get_ip;"   /* lr = pc */      \
+           "m_libcassert_get_ip:\n"                       \
+           "mflr %0;"                  /* %0 = pc */      \
+           "mtlr 0;"                   /* restore lr */   \
+           "mr %1,1;"                  /* %1 = r1 */      \
+           "mr %2,0;"                  /* %2 = lr */      \
+           : "=r" (cia), "=r" (r1), "=r" (lr)             \
+           : /* reads none */                             \
+           : "r0" /* trashed */                           \
+        );                                                \
+        srP->r_pc = (ULong)cia;                           \
+        srP->r_sp = (ULong)r1;                            \
+        srP->misc.PPC32.lr = lr;                          \
+      }
 #elif defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
-#  define GET_REAL_PC_SP_AND_FP(pc, sp, fp)                   \
-      asm("mflr 0;"                   /* r0 = lr */           \
-          "bl .m_libcassert_get_ip;"  /* lr = pc */           \
-          ".m_libcassert_get_ip:\n"                           \
-          "mflr %0;"                \
-          "mtlr 0;"                   /* restore lr */        \
-          "mr %1,1;"                \
-          "mr %2,1;"                \
-          : "=r" (pc),              \
-            "=r" (sp),              \
-            "=r" (fp)               \
-          : /* reads none */        \
-          : "r0" /* trashed */ );
+#  define GET_STARTREGS(srP)                              \
+      { ULong cia, r1, lr;                                \
+        __asm__ __volatile__(                             \
+           "mflr 0;"                   /* r0 = lr */      \
+           "bl .m_libcassert_get_ip;"  /* lr = pc */      \
+           ".m_libcassert_get_ip:\n"                      \
+           "mflr %0;"                  /* %0 = pc */      \
+           "mtlr 0;"                   /* restore lr */   \
+           "mr %1,1;"                  /* %1 = r1 */      \
+           "mr %2,0;"                  /* %2 = lr */      \
+           : "=r" (cia), "=r" (r1), "=r" (lr)             \
+           : /* reads none */                             \
+           : "r0" /* trashed */                           \
+        );                                                \
+        srP->r_pc = cia;                                  \
+        srP->r_sp = r1;                                   \
+        srP->misc.PPC64.lr = lr;                          \
+      }
+#elif defined(VGP_arm_linux)
+#  define GET_STARTREGS(srP)                              \
+      { UInt block[5];                                    \
+        __asm__ __volatile__(                             \
+           "str r15, [%0, #+0];"                          \
+           "str r14, [%0, #+4];"                          \
+           "str r13, [%0, #+8];"                          \
+           "str r12, [%0, #+12];"                         \
+           "str r11, [%0, #+16];"                         \
+           : /* out */                                    \
+           : /* in */ "r"(&block[0])                      \
+           : /* trash */ "memory"                         \
+        );                                                \
+        (srP)->r_pc = block[0] - 8;                       \
+        (srP)->r_sp = block[1];                           \
+        (srP)->misc.ARM.r14 = block[2];                   \
+        (srP)->misc.ARM.r12 = block[3];                   \
+        (srP)->misc.ARM.r11 = block[4];                   \
+      }
 #else
 #  error Unknown platform
 #endif
@@ -129,8 +172,8 @@
 }
 
 __attribute__ ((noreturn))
-static void report_and_quit ( const Char* report, 
-                              Addr ip, Addr sp, Addr fp, Addr lr )
+static void report_and_quit ( const Char* report,
+                              UnwindStartRegs* startRegsIN )
 {
    Addr stacktop;
    Addr ips[BACKTRACE_DEPTH];
@@ -141,8 +184,13 @@
    // If necessary, fake up an ExeContext which is of our actual real CPU
    // state.  Could cause problems if we got the panic/exception within the
    // execontext/stack dump/symtab code.  But it's better than nothing.
-   if (0 == ip && 0 == sp && 0 == fp) {
-       GET_REAL_PC_SP_AND_FP(ip, sp, fp);
+   UnwindStartRegs startRegs;
+   VG_(memset)(&startRegs, 0, sizeof(startRegs));
+
+   if (startRegsIN == NULL) {
+      GET_STARTREGS(&startRegs);
+   } else {
+      startRegs = *startRegsIN;
    }
  
    stacktop = tst->os_state.valgrind_stack_init_SP;
@@ -153,7 +201,7 @@
          ips, BACKTRACE_DEPTH, 
          NULL/*array to dump SP values in*/,
          NULL/*array to dump FP values in*/,
-         ip, sp, fp, lr, sp, stacktop
+         &startRegs, stacktop
       );
    VG_(clo_xml) = False;
    VG_(pp_StackTrace) (ips, n_ips);
@@ -214,32 +262,32 @@
    if (!VG_STREQ(buf, ""))
       VG_(printf)("%s: %s\n", component, buf );
 
-   report_and_quit(bugs_to, 0,0,0,0);
+   report_and_quit(bugs_to, NULL);
 }
 
 __attribute__ ((noreturn))
 static void panic ( Char* name, Char* report, Char* str,
-                    Addr ip, Addr sp, Addr fp, Addr lr )
+                    UnwindStartRegs* startRegs )
 {
    if (VG_(clo_xml))
       VG_(printf_xml)("</valgrindoutput>\n");
    VG_(printf)("\n%s: the 'impossible' happened:\n   %s\n", name, str);
-   report_and_quit(report, ip, sp, fp, lr);
+   report_and_quit(report, startRegs);
 }
 
-void VG_(core_panic_at) ( Char* str, Addr ip, Addr sp, Addr fp, Addr lr )
+void VG_(core_panic_at) ( Char* str, UnwindStartRegs* startRegs )
 {
-   panic("valgrind", VG_BUGS_TO, str, ip, sp, fp, lr);
+   panic("valgrind", VG_BUGS_TO, str, startRegs);
 }
 
 void VG_(core_panic) ( Char* str )
 {
-   VG_(core_panic_at)(str, 0,0,0,0);
+   VG_(core_panic_at)(str, NULL);
 }
 
 void VG_(tool_panic) ( Char* str )
 {
-   panic(VG_(details).name, VG_(details).bug_reports_to, str, 0,0,0,0);
+   panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
 }
 
 /* Print some helpful-ish text about unimplemented things, and give up. */