Author: fabient
Date: Tue Mar 14 16:06:57 2017
New Revision: 315270
URL: https://svnweb.freebsd.org/changeset/base/315270

Log:
  Fix arm stack frame walking support:
  - Adjust stack offset for Clang
  - Correctly fill registers for fake stack frame (soft PMC)
  
  MFC after:    1 week
  Sponsored by: Stormshield
  Differential Revision:        https://reviews.freebsd.org/D7396

Modified:
  head/sys/arm/include/pmc_mdep.h
  head/sys/dev/hwpmc/hwpmc_arm.c

Modified: head/sys/arm/include/pmc_mdep.h
==============================================================================
--- head/sys/arm/include/pmc_mdep.h     Tue Mar 14 16:01:36 2017        
(r315269)
+++ head/sys/arm/include/pmc_mdep.h     Tue Mar 14 16:06:57 2017        
(r315270)
@@ -70,7 +70,9 @@ union pmc_md_pmc {
 /* Build a fake kernel trapframe from current instruction pointer. */
 #define PMC_FAKE_TRAPFRAME(TF)                                         \
        do {                                                            \
+       (TF)->tf_spsr = PSR_SVC32_MODE;                                 \
        __asm __volatile("mov %0, pc" : "=r" ((TF)->tf_pc));            \
+       __asm __volatile("mov %0, r11" : "=r" ((TF)->tf_r11));          \
        } while (0)
 
 /*

Modified: head/sys/dev/hwpmc/hwpmc_arm.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_arm.c      Tue Mar 14 16:01:36 2017        
(r315269)
+++ head/sys/dev/hwpmc/hwpmc_arm.c      Tue Mar 14 16:06:57 2017        
(r315270)
@@ -42,6 +42,17 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_param.h>
 #include <vm/pmap.h>
 
+/* XXX: Userland code compiled with gcc will need an heuristic
+ * to be correctly detected. 
+ */
+#ifdef __clang__
+#define PC_OFF 1
+#define FP_OFF 0
+#else
+#define PC_OFF -1
+#define FP_OFF -3
+#endif
+
 struct pmc_mdep *
 pmc_md_initialize()
 {
@@ -100,7 +111,7 @@ pmc_save_kernel_callchain(uintptr_t *cc,
 
        for (count = 1; count < maxsamples; count++) {
                /* Use saved lr as pc. */
-               r = fp - sizeof(uintptr_t);
+               r = fp + PC_OFF * sizeof(uintptr_t);
                if (!PMC_IN_KERNEL_STACK(r, stackstart, stackend))
                        break;
                pc = *(uintptr_t *)r;
@@ -110,7 +121,7 @@ pmc_save_kernel_callchain(uintptr_t *cc,
                *cc++ = pc;
 
                /* Switch to next frame up */
-               r = fp - 3 * sizeof(uintptr_t);
+               r = fp + FP_OFF * sizeof(uintptr_t);
                if (!PMC_IN_KERNEL_STACK(r, stackstart, stackend))
                        break;
                fp = *(uintptr_t *)r;
@@ -147,7 +158,7 @@ pmc_save_user_callchain(uintptr_t *cc, i
 
        for (count = 1; count < maxsamples; count++) {
                /* Use saved lr as pc. */
-               r = fp - sizeof(uintptr_t);
+               r = fp + PC_OFF * sizeof(uintptr_t);
                if (copyin((void *)r, &pc, sizeof(pc)) != 0)
                        break;
                if (!PMC_IN_USERSPACE(pc))
@@ -157,7 +168,7 @@ pmc_save_user_callchain(uintptr_t *cc, i
 
                /* Switch to next frame up */
                oldfp = fp;
-               r = fp - 3 * sizeof(uintptr_t);
+               r = fp + FP_OFF * sizeof(uintptr_t);
                if (copyin((void *)r, &fp, sizeof(fp)) != 0)
                        break;
                if (fp < oldfp || !PMC_IN_USERSPACE(fp))
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to