diff options
author | Fabien Thomas <fabient@FreeBSD.org> | 2017-03-14 16:06:57 +0000 |
---|---|---|
committer | Fabien Thomas <fabient@FreeBSD.org> | 2017-03-14 16:06:57 +0000 |
commit | d42aefee43e74077aa612b066cf726ca1233dc00 (patch) | |
tree | 07f4be81394c5c2f255e27f32f1541103d668251 /sys/dev/hwpmc | |
parent | 0a1b74a3d1c8c8c88fb85425354f38916263e3fc (diff) | |
download | src-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.c | 19 |
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)) |