aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/hwpmc
diff options
context:
space:
mode:
authorFabien Thomas <fabient@FreeBSD.org>2017-03-14 16:06:57 +0000
committerFabien Thomas <fabient@FreeBSD.org>2017-03-14 16:06:57 +0000
commitd42aefee43e74077aa612b066cf726ca1233dc00 (patch)
tree07f4be81394c5c2f255e27f32f1541103d668251 /sys/dev/hwpmc
parent0a1b74a3d1c8c8c88fb85425354f38916263e3fc (diff)
downloadsrc-d42aefee43e74077aa612b066cf726ca1233dc00.tar.gz
src-d42aefee43e74077aa612b066cf726ca1233dc00.zip
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
Notes
Notes: svn path=/head/; revision=315270
Diffstat (limited to 'sys/dev/hwpmc')
-rw-r--r--sys/dev/hwpmc/hwpmc_arm.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/sys/dev/hwpmc/hwpmc_arm.c b/sys/dev/hwpmc/hwpmc_arm.c
index a2a25a98d2f3..94f29922290b 100644
--- a/sys/dev/hwpmc/hwpmc_arm.c
+++ b/sys/dev/hwpmc/hwpmc_arm.c
@@ -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, int maxsamples,
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, int maxsamples,
*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, int maxsamples,
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, int maxsamples,
/* 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))