summaryrefslogtreecommitdiff
path: root/usr/src/uts/sparc/dtrace/dtrace_isa.c
diff options
context:
space:
mode:
authorahl <none@none>2005-07-20 01:15:45 -0700
committerahl <none@none>2005-07-20 01:15:45 -0700
commit0b38a8bdfd75ac6144f9d462bb38d0c1b3f0ca50 (patch)
treeb1914d8b26048f30b052b54b9625a9f6f8d153ca /usr/src/uts/sparc/dtrace/dtrace_isa.c
parentb52a2671b74561fd8e88284bba4b0b834687951e (diff)
downloadillumos-gate-0b38a8bdfd75ac6144f9d462bb38d0c1b3f0ca50.tar.gz
4970475 There should be a stackdepth equivalent for userland
5084954 value of dip can be incorrect in autovec 6181505 dtrace sysinfo:::modload probe does not fire when using 'modload' 6265417 schedctl-yield isn't listed in sdt_subr.c 6272558 gcc and dtrace don't get along 6276101 dtrace -G behaves strangely with multiple scripts 6284880 intrstat can leak dynamic variable state 6295662 plockstat needs more characters for stack addresses 6296903 invalid memory accesses clear other DTrace error bits
Diffstat (limited to 'usr/src/uts/sparc/dtrace/dtrace_isa.c')
-rw-r--r--usr/src/uts/sparc/dtrace/dtrace_isa.c139
1 files changed, 100 insertions, 39 deletions
diff --git a/usr/src/uts/sparc/dtrace/dtrace_isa.c b/usr/src/uts/sparc/dtrace/dtrace_isa.c
index 615738c8ea..4c62ab0ec0 100644
--- a/usr/src/uts/sparc/dtrace/dtrace_isa.c
+++ b/usr/src/uts/sparc/dtrace/dtrace_isa.c
@@ -34,6 +34,7 @@
#include <sys/machpcb.h>
#include <sys/procfs_isa.h>
#include <sys/cmn_err.h>
+#include <sys/sysmacros.h>
#define DTRACE_FMT3OP3_MASK 0x81000000
#define DTRACE_FMT3OP3 0x80000000
@@ -55,6 +56,7 @@
#define DTRACE_JMPL 0x81c00000
extern int dtrace_getupcstack_top(uint64_t *, int, uintptr_t *);
+extern int dtrace_getustackdepth_top(uintptr_t *);
extern ulong_t dtrace_getreg_win(uint_t, uint_t);
extern void dtrace_putreg_win(uint_t, ulong_t);
extern int dtrace_fish(int, int, uintptr_t *);
@@ -74,8 +76,8 @@ extern int dtrace_fish(int, int, uintptr_t *);
* deliver as correct a stack as possible. Details on the issues
* surrounding stack correctness are found below.
*
- * (c) dtrace_getpcstack() _always_ fills in pstack_limit pc_t's -- filling
- * in the difference between the stack depth and pstack_limit with NULLs.
+ * (c) dtrace_getpcstack() _always_ fills in pcstack_limit pc_t's -- filling
+ * in the difference between the stack depth and pcstack_limit with NULLs.
* Due to this behavior dtrace_getpcstack() returns void.
*
* (d) dtrace_getpcstack() takes a third parameter, aframes, that
@@ -306,16 +308,77 @@ leaf:
}
}
+static int
+dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t sp)
+{
+ proc_t *p = curproc;
+ int ret = 0;
+
+ ASSERT(pcstack == NULL || pcstack_limit > 0);
+
+ if (p->p_model == DATAMODEL_NATIVE) {
+ for (;;) {
+ struct frame *fr = (struct frame *)(sp + STACK_BIAS);
+ uintptr_t pc;
+
+ if (sp == 0 || fr == NULL ||
+ !IS_P2ALIGNED((uintptr_t)fr, STACK_ALIGN))
+ break;
+
+ pc = dtrace_fulword(&fr->fr_savpc);
+ sp = dtrace_fulword(&fr->fr_savfp);
+
+ if (pc == 0)
+ break;
+
+ ret++;
+
+ if (pcstack != NULL) {
+ *pcstack++ = pc;
+ pcstack_limit--;
+ if (pcstack_limit == 0)
+ break;
+ }
+ }
+ } else {
+ for (;;) {
+ struct frame32 *fr = (struct frame32 *)sp;
+ uint32_t pc;
+
+ if (sp == 0 ||
+ !IS_P2ALIGNED((uintptr_t)fr, STACK_ALIGN32))
+ break;
+
+ pc = dtrace_fuword32(&fr->fr_savpc);
+ sp = dtrace_fuword32(&fr->fr_savfp);
+
+ if (pc == 0)
+ break;
+
+ ret++;
+
+ if (pcstack != NULL) {
+ *pcstack++ = pc;
+ pcstack_limit--;
+ if (pcstack_limit == 0)
+ break;
+ }
+ }
+ }
+
+ return (ret);
+}
+
void
dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
{
klwp_t *lwp = ttolwp(curthread);
- proc_t *p = ttoproc(curthread);
+ proc_t *p = curproc;
struct regs *rp;
uintptr_t sp;
int n;
- if (lwp == NULL || p == NULL || lwp->lwp_regs == NULL)
+ if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL)
return;
if (pcstack_limit <= 0)
@@ -327,7 +390,6 @@ dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
if (pcstack_limit <= 0)
return;
- rp = lwp->lwp_regs;
*pcstack++ = (uint64_t)rp->r_pc;
pcstack_limit--;
@@ -349,46 +411,44 @@ dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
pcstack += n;
pcstack_limit -= n;
+ if (pcstack_limit <= 0)
+ return;
- if (p->p_model == DATAMODEL_NATIVE) {
- while (pcstack_limit > 0) {
- struct frame *fr = (struct frame *)(sp + STACK_BIAS);
- uintptr_t pc;
+ n = dtrace_getustack_common(pcstack, pcstack_limit, sp);
+ ASSERT(n >= 0);
+ ASSERT(n <= pcstack_limit);
- if (sp == 0 || fr == NULL ||
- ((uintptr_t)&fr->fr_savpc & 3) != 0 ||
- ((uintptr_t)&fr->fr_savfp & 3) != 0)
- break;
+ pcstack += n;
+ pcstack_limit -= n;
- pc = dtrace_fulword(&fr->fr_savpc);
- sp = dtrace_fulword(&fr->fr_savfp);
+ while (pcstack_limit-- > 0)
+ *pcstack++ = NULL;
+}
- if (pc == 0)
- break;
+int
+dtrace_getustackdepth(void)
+{
+ klwp_t *lwp = ttolwp(curthread);
+ proc_t *p = curproc;
+ struct regs *rp;
+ uintptr_t sp;
+ int n = 1;
- *pcstack++ = pc;
- pcstack_limit--;
- }
- } else {
- while (pcstack_limit > 0) {
- struct frame32 *fr = (struct frame32 *)sp;
- uint32_t pc;
+ if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL)
+ return (0);
- if (sp == 0 ||
- ((uintptr_t)&fr->fr_savpc & 3) != 0 ||
- ((uintptr_t)&fr->fr_savfp & 3) != 0)
- break;
+ if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT))
+ return (-1);
- pc = dtrace_fuword32(&fr->fr_savpc);
- sp = dtrace_fuword32(&fr->fr_savfp);
+ if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY))
+ n++;
- *pcstack++ = pc;
- pcstack_limit--;
- }
- }
+ sp = rp->r_sp;
- while (pcstack_limit-- > 0)
- *pcstack++ = NULL;
+ n += dtrace_getustackdepth_top(&sp);
+ n += dtrace_getustack_common(NULL, 0, sp);
+
+ return (n);
}
void
@@ -399,7 +459,7 @@ dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
struct regs *rp;
uintptr_t sp;
- if (lwp == NULL || p == NULL || lwp->lwp_regs == NULL)
+ if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL)
return;
if (pcstack_limit <= 0)
@@ -411,8 +471,6 @@ dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
if (pcstack_limit <= 0)
return;
- rp = lwp->lwp_regs;
-
if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
*fpstack++ = 0;
*pcstack++ = (uint64_t)rp->r_pc;
@@ -469,6 +527,9 @@ dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
pc = dtrace_fuword32(&fr->fr_savpc);
sp = dtrace_fuword32(&fr->fr_savfp);
+ if (pc == 0)
+ break;
+
*fpstack++ = sp;
*pcstack++ = pc;
pcstack_limit--;