[DTrace-devel] [PATCH 1/2] Unify the handling of stack traces in the consumer
Kris Van Hees
kris.van.hees at oracle.com
Tue Sep 23 16:01:24 UTC 2025
Distinguishing between kernel stacks and userspace stacks was done
based on the action id, even when used outside of action context
(i.e. in aggregation keys). That is far from ideal.
Encode the stack type along with the nframes and strsize values in
the data record description argument for stack() and ustack()
records.
The macros for managing that argument are moved to dt_impl.h since
they are internal to the DTrace implementation.
All printing of stack traces is now consolidated in dt_printf.c as
well.
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
include/dtrace/actions_defines.h | 5 -
libdtrace/dt_cg.c | 6 +-
libdtrace/dt_consume.c | 256 ++---------------------------
libdtrace/dt_impl.h | 13 ++
libdtrace/dt_printf.c | 266 ++++++++++++++++++++++++++++---
libdtrace/dt_printf.h | 12 +-
6 files changed, 275 insertions(+), 283 deletions(-)
diff --git a/include/dtrace/actions_defines.h b/include/dtrace/actions_defines.h
index 1a9c1a81..7c2f7dda 100644
--- a/include/dtrace/actions_defines.h
+++ b/include/dtrace/actions_defines.h
@@ -156,11 +156,6 @@
(uint16_t)(((x) & DTRACE_LLQUANTIZE_FACTORMASK) >> \
DTRACE_LLQUANTIZE_FACTORSHIFT)
-#define DTRACE_USTACK_NFRAMES(x) (uint32_t)((x) & UINT32_MAX)
-#define DTRACE_USTACK_STRSIZE(x) (uint32_t)((x) >> 32)
-#define DTRACE_USTACK_ARG(x, y) \
- ((((uint64_t)(y)) << 32) | ((x) & UINT32_MAX))
-
#ifndef _LP64
# ifndef _LITTLE_ENDIAN
# define DTRACE_PTR(type, name) uint32_t name##pad; type *name
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 1f120e1d..2b81f2e0 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -2701,7 +2701,7 @@ dt_cg_stack_arg(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_actkind_t kind)
strsize = arg1->dn_value;
}
- return DTRACE_USTACK_ARG(nframes, strsize);
+ return DTRACE_STACK_ARG(kind == DTRACEACT_USTACK, nframes, strsize);
}
/*
@@ -2738,7 +2738,7 @@ dt_cg_act_stack_sub(dt_pcb_t *pcb, dt_node_t *dnp, int reg, int off, dtrace_actk
/* Get sizing information from dnp->dn_arg. */
arg = dt_cg_stack_arg(dtp, dnp, kind);
prefsz = kind == DTRACEACT_USTACK ? sizeof(uint64_t) : 0;
- nframes = DTRACE_USTACK_NFRAMES(arg);
+ nframes = DTRACE_STACK_NFRAMES(arg);
stacksize = nframes * sizeof(uint64_t);
/* Handle alignment and reserve space in the output buffer. */
@@ -8698,7 +8698,7 @@ dt_cg_agg(dt_pcb_t *pcb, dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
case DT_ACT_USTACK:
arg = dt_cg_stack_arg(dtp, knp, DTRACEACT_USTACK);
kind = DTRACEACT_USTACK;
- size = 8 + 8 * DTRACE_USTACK_NFRAMES(arg);
+ size = 8 + 8 * DTRACE_STACK_NFRAMES(arg);
break;
case DT_ACT_JSTACK:
kind = DTRACEACT_JSTACK;
diff --git a/libdtrace/dt_consume.c b/libdtrace/dt_consume.c
index 280ed42a..eca2139f 100644
--- a/libdtrace/dt_consume.c
+++ b/libdtrace/dt_consume.c
@@ -1079,232 +1079,6 @@ dt_print_tracemem(dtrace_hdl_t *dtp, FILE *fp, const dtrace_recdesc_t *rec,
return nconsumed;
}
-int
-dt_print_stack(dtrace_hdl_t *dtp, FILE *fp, const char *format,
- caddr_t addr, int depth, int size)
-{
- dtrace_syminfo_t dts;
- GElf_Sym sym;
- int i, indent;
- char c[PATH_MAX * 2];
- uint64_t pc;
-
- if (dt_printf(dtp, fp, "\n") < 0)
- return -1;
-
- if (format == NULL)
- format = "%s";
-
- if (dtp->dt_options[DTRACEOPT_STACKINDENT] != DTRACEOPT_UNSET)
- indent = (int)dtp->dt_options[DTRACEOPT_STACKINDENT];
- else
- indent = _dtrace_stkindent;
-
- for (i = 0; i < depth; i++) {
- switch (size) {
- case sizeof(uint32_t):
- /* LINTED - alignment */
- pc = *((uint32_t *)addr);
- break;
-
- case sizeof(uint64_t):
- /* LINTED - alignment */
- pc = *((uint64_t *)addr);
- break;
-
- default:
- return dt_set_errno(dtp, EDT_BADSTACKPC);
- }
-
- if (pc == 0)
- break;
-
- addr += size;
-
- if (dt_printf(dtp, fp, "%*s", indent, "") < 0)
- return -1;
-
- if (dtrace_lookup_by_addr(dtp, pc, &sym, &dts) == 0) {
- if (pc > sym.st_value)
- snprintf(c, sizeof(c), "%s`%s+0x%llx",
- dts.object, dts.name,
- (long long unsigned)pc - sym.st_value);
- else
- snprintf(c, sizeof(c), "%s`%s",
- dts.object, dts.name);
- } else {
- /*
- * We'll repeat the lookup, but this time we'll specify
- * a NULL GElf_Sym -- indicating that we're only
- * interested in the containing module.
- */
- if (dtrace_lookup_by_addr(dtp, pc, NULL, &dts) == 0)
- snprintf(c, sizeof(c), "%s`0x%llx",
- dts.object, (long long unsigned)pc);
- else
- snprintf(c, sizeof(c), "0x%llx",
- (long long unsigned)pc);
- }
-
- if (dt_printf(dtp, fp, format, c) < 0)
- return -1;
-
- if (dt_printf(dtp, fp, "\n") < 0)
- return -1;
- }
-
- return 0;
-}
-
-int
-dt_print_ustack(dtrace_hdl_t *dtp, FILE *fp, const char *format,
- caddr_t addr, uint64_t arg)
-{
- /* LINTED - alignment */
- uint64_t *pc = ((uint64_t *)addr);
- uint32_t depth = DTRACE_USTACK_NFRAMES(arg);
- uint32_t strsize = DTRACE_USTACK_STRSIZE(arg);
- const char *strbase = addr + (depth + 1) * sizeof(uint64_t);
- const char *str = strsize ? strbase : NULL;
- int err = 0;
-
- const char *name;
- char objname[PATH_MAX], c[PATH_MAX * 2];
- GElf_Sym sym;
- int i, indent;
- pid_t pid = -1, tgid;
-
- if (depth == 0)
- return 0;
-
- tgid = (pid_t)*pc++;
-
- if (dt_printf(dtp, fp, "\n") < 0)
- return -1;
-
- if (format == NULL)
- format = "%s";
-
- if (dtp->dt_options[DTRACEOPT_STACKINDENT] != DTRACEOPT_UNSET)
- indent = (int)dtp->dt_options[DTRACEOPT_STACKINDENT];
- else
- indent = _dtrace_stkindent;
-
- /*
- * Ultimately, we need to add an entry point in the library vector for
- * determining <symbol, offset> from <tgid, address>. For now, if
- * this is a vector open, we just print the raw address or string.
- */
- if (dtp->dt_vector == NULL)
- pid = dt_proc_grab_lock(dtp, tgid, DTRACE_PROC_WAITING |
- DTRACE_PROC_SHORTLIVED);
-
- for (i = 0; i < depth && pc[i] != 0; i++) {
- const prmap_t *map;
-
- if ((err = dt_printf(dtp, fp, "%*s", indent, "")) < 0)
- break;
- if (dtp->dt_options[DTRACEOPT_NORESOLVE] != DTRACEOPT_UNSET
- && pid >= 0) {
- if (dt_Pobjname(dtp, pid, pc[i], objname,
- sizeof(objname)) != NULL) {
- const prmap_t *pmap = NULL;
- uint64_t offset = pc[i];
-
- pmap = dt_Paddr_to_map(dtp, pid, pc[i]);
-
- if (pmap)
- offset = pc[i] - pmap->pr_vaddr;
-
- snprintf(c, sizeof(c), "%s:0x%llx",
- dt_basename(objname), (unsigned long long)offset);
-
- } else
- snprintf(c, sizeof(c), "0x%llx",
- (unsigned long long)pc[i]);
-
- } else if (pid >= 0 && dt_Plookup_by_addr(dtp, pid, pc[i],
- &name, &sym) == 0) {
- if (dt_Pobjname(dtp, pid, pc[i], objname,
- sizeof(objname)) != NULL) {
- if (pc[i] > sym.st_value)
- snprintf(c, sizeof(c), "%s`%s+0x%llx",
- dt_basename(objname), name,
- (unsigned long long)(pc[i] - sym.st_value));
- else
- snprintf(c, sizeof(c), "%s`%s",
- dt_basename(objname), name);
- } else
- snprintf(c, sizeof(c), "0x%llx",
- (unsigned long long)pc[i]);
- /* Allocated by Plookup_by_addr. */
- free((char *)name);
- } else if (str != NULL && str[0] != '\0' && str[0] != '@' &&
- (pid >= 0 &&
- ((map = dt_Paddr_to_map(dtp, pid, pc[i])) == NULL ||
- (map->pr_mflags & MA_WRITE)))) {
- /*
- * If the current string pointer in the string table
- * does not point to an empty string _and_ the program
- * counter falls in a writable region, we'll use the
- * string from the string table instead of the raw
- * address. This last condition is necessary because
- * some (broken) ustack helpers will return a string
- * even for a program counter that they can't
- * identify. If we have a string for a program
- * counter that falls in a segment that isn't
- * writable, we assume that we have fallen into this
- * case and we refuse to use the string.
- */
- snprintf(c, sizeof(c), "%s", str);
- } else {
- if (pid >= 0 && dt_Pobjname(dtp, pid, pc[i], objname,
- sizeof(objname)) != NULL)
- snprintf(c, sizeof(c), "%s`0x%llx",
- dt_basename(objname), (unsigned long long)pc[i]);
- else
- snprintf(c, sizeof(c), "0x%llx",
- (unsigned long long)pc[i]);
- }
-
- if ((err = dt_printf(dtp, fp, format, c)) < 0)
- break;
-
- if ((err = dt_printf(dtp, fp, "\n")) < 0)
- break;
-
- if (str != NULL && str[0] == '@') {
- /*
- * If the first character of the string is an "at" sign,
- * then the string is inferred to be an annotation --
- * and it is printed out beneath the frame and offset
- * with brackets.
- */
- if ((err = dt_printf(dtp, fp, "%*s", indent, "")) < 0)
- break;
-
- snprintf(c, sizeof(c), " [ %s ]", &str[1]);
-
- if ((err = dt_printf(dtp, fp, format, c)) < 0)
- break;
-
- if ((err = dt_printf(dtp, fp, "\n")) < 0)
- break;
- }
-
- if (str != NULL) {
- str += strlen(str) + 1;
- if (str - strbase >= strsize)
- str = NULL;
- }
- }
-
- if (pid >= 0)
- dt_proc_release_unlock(dtp, pid);
-
- return err;
-}
-
static int
dt_print_usym(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr, dtrace_actkind_t act)
{
@@ -1355,7 +1129,7 @@ dt_print_umod(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr)
format = " %-50s";
/*
- * See the comment in dt_print_ustack() for the rationale for
+ * See the comment in dt_print_stack_user() for the rationale for
* printing raw addresses in the vectored case.
*/
if (dtp->dt_vector == NULL)
@@ -1660,12 +1434,15 @@ dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
switch (act) {
case DTRACEACT_STACK:
- return dt_print_stack(dtp, fp, NULL, addr, rec->dtrd_arg,
- rec->dtrd_size / rec->dtrd_arg);
+ case DTRACEACT_USTACK: {
+ dtrace_probedata_t pdat;
- case DTRACEACT_USTACK:
- case DTRACEACT_JSTACK:
- return dt_print_ustack(dtp, fp, NULL, addr, rec->dtrd_arg);
+ /* dt_print_stack() uses dtpda_data only */
+ memset(&pdat, 0, sizeof(pdat));
+ pdat.dtpda_data = addr;
+
+ return dt_print_stack(dtp, fp, NULL, &pdat, rec, 1, NULL, 0);
+ }
case DTRACEACT_USYM:
case DTRACEACT_UADDR:
@@ -2467,14 +2244,6 @@ dt_consume_one_probe(dtrace_hdl_t *dtp, FILE *fp, char *data, uint32_t size,
return dt_set_errno(dtp, EDT_BADRVAL);
switch (act) {
- case DTRACEACT_STACK: {
- int depth = rec->dtrd_arg;
-
- if (dt_print_stack(dtp, fp, NULL, recdata,
- depth, rec->dtrd_size / depth) < 0)
- return -1;
- continue;
- }
case DTRACEACT_SYM:
if (dt_print_sym(dtp, fp, NULL, recdata) < 0)
return -1;
@@ -2483,11 +2252,10 @@ dt_consume_one_probe(dtrace_hdl_t *dtp, FILE *fp, char *data, uint32_t size,
if (dt_print_mod(dtp, fp, NULL, recdata) < 0)
return -1;
continue;
+ case DTRACEACT_STACK:
case DTRACEACT_USTACK:
- if (dt_print_ustack(dtp, fp, NULL,
- recdata, rec->dtrd_arg) < 0)
- return -1;
- continue;
+ func = dt_print_stack;
+ break;
case DTRACEACT_USYM:
case DTRACEACT_UADDR:
if (dt_print_usym(dtp, fp, recdata, act) < 0)
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index 7d8e4432..4dc4c9a7 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -236,6 +236,19 @@ typedef struct dt_tstring {
int in_use; /* In use (1) or not (0) */
} dt_tstring_t;
+/*
+ * The stack()/ustack() data record argument encodes:
+ * - the stack type (kernel or userspace)
+ * - the number of frames in the stack trace
+ * - the size of the optional string area for ustack()
+ */
+#define DTRACE_STACK_IS_USER(x) ((x) & (1 << 31))
+#define DTRACE_STACK_NFRAMES(x) (uint32_t)((x) & INT32_MAX)
+#define DTRACE_STACK_STRSIZE(x) (uint32_t)((x) >> 32)
+#define DTRACE_STACK_ARG(t, x, y) ((((uint64_t)(y)) << 32) | \
+ ((t) ? (1UL << 31) : 0) | \
+ ((x) & INT32_MAX))
+
typedef struct dt_dirpath {
dt_list_t dir_list; /* linked-list forward/back pointers */
char *dir_path; /* directory pathname */
diff --git a/libdtrace/dt_printf.c b/libdtrace/dt_printf.c
index 1e01d468..4c276c26 100644
--- a/libdtrace/dt_printf.c
+++ b/libdtrace/dt_printf.c
@@ -374,6 +374,205 @@ pfprint_uaddr(dtrace_hdl_t *dtp, FILE *fp, const char *format,
return dt_printf(dtp, fp, format, s);
}
+static int
+dt_print_stack_kernel(dtrace_hdl_t *dtp, FILE *fp, const char *format,
+ caddr_t addr, int indent, uint32_t depth)
+{
+ dtrace_syminfo_t dts;
+ GElf_Sym sym;
+ int i;
+ char c[PATH_MAX * 2];
+ uint64_t pc;
+
+ if (format == NULL)
+ format = "%s";
+
+ for (i = 0; i < depth; i++) {
+ pc = *((uint64_t *)addr);
+ if (pc == 0)
+ break;
+
+ addr += sizeof(pc);
+
+ if (dt_printf(dtp, fp, "%*s", indent, "") < 0)
+ return -1;
+
+ if (dtrace_lookup_by_addr(dtp, pc, &sym, &dts) == 0) {
+ if (pc > sym.st_value)
+ snprintf(c, sizeof(c), "%s`%s+0x%llx",
+ dts.object, dts.name,
+ (long long unsigned)pc - sym.st_value);
+ else
+ snprintf(c, sizeof(c), "%s`%s",
+ dts.object, dts.name);
+ } else {
+ /*
+ * We'll repeat the lookup, but this time we'll specify
+ * a NULL GElf_Sym -- indicating that we're only
+ * interested in the containing module.
+ */
+ if (dtrace_lookup_by_addr(dtp, pc, NULL, &dts) == 0)
+ snprintf(c, sizeof(c), "%s`0x%llx",
+ dts.object, (long long unsigned)pc);
+ else
+ snprintf(c, sizeof(c), "0x%llx",
+ (long long unsigned)pc);
+ }
+
+ if (dt_printf(dtp, fp, format, c) < 0)
+ return -1;
+
+ if (dt_printf(dtp, fp, "\n") < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+dt_print_stack_user(dtrace_hdl_t *dtp, FILE *fp, const char *format,
+ caddr_t addr, int indent, uint32_t depth, uint32_t strsize)
+{
+ /* LINTED - alignment */
+ uint64_t *pc = ((uint64_t *)addr);
+ const char *strbase = addr + (depth + 1) * sizeof(uint64_t);
+ const char *str = strsize ? strbase : NULL;
+ int err = 0;
+
+ const char *name;
+ char objname[PATH_MAX], c[PATH_MAX * 2];
+ GElf_Sym sym;
+ int i;
+ pid_t pid = -1, tgid;
+
+ if (depth == 0)
+ return 0;
+
+ tgid = (pid_t)*pc++;
+
+ if (format == NULL)
+ format = "%s";
+
+ if (dtp->dt_options[DTRACEOPT_STACKINDENT] != DTRACEOPT_UNSET)
+ indent = (int)dtp->dt_options[DTRACEOPT_STACKINDENT];
+ else
+ indent = _dtrace_stkindent;
+
+ /*
+ * Ultimately, we need to add an entry point in the library vector for
+ * determining <symbol, offset> from <tgid, address>. For now, if
+ * this is a vector open, we just print the raw address or string.
+ */
+ if (dtp->dt_vector == NULL)
+ pid = dt_proc_grab_lock(dtp, tgid, DTRACE_PROC_WAITING |
+ DTRACE_PROC_SHORTLIVED);
+
+ for (i = 0; i < depth && pc[i] != 0; i++) {
+ const prmap_t *map;
+
+ if ((err = dt_printf(dtp, fp, "%*s", indent, "")) < 0)
+ break;
+ if (dtp->dt_options[DTRACEOPT_NORESOLVE] != DTRACEOPT_UNSET
+ && pid >= 0) {
+ if (dt_Pobjname(dtp, pid, pc[i], objname,
+ sizeof(objname)) != NULL) {
+ const prmap_t *pmap = NULL;
+ uint64_t offset = pc[i];
+
+ pmap = dt_Paddr_to_map(dtp, pid, pc[i]);
+
+ if (pmap)
+ offset = pc[i] - pmap->pr_vaddr;
+
+ snprintf(c, sizeof(c), "%s:0x%llx",
+ dt_basename(objname), (unsigned long long)offset);
+
+ } else
+ snprintf(c, sizeof(c), "0x%llx",
+ (unsigned long long)pc[i]);
+
+ } else if (pid >= 0 && dt_Plookup_by_addr(dtp, pid, pc[i],
+ &name, &sym) == 0) {
+ if (dt_Pobjname(dtp, pid, pc[i], objname,
+ sizeof(objname)) != NULL) {
+ if (pc[i] > sym.st_value)
+ snprintf(c, sizeof(c), "%s`%s+0x%llx",
+ dt_basename(objname), name,
+ (unsigned long long)(pc[i] - sym.st_value));
+ else
+ snprintf(c, sizeof(c), "%s`%s",
+ dt_basename(objname), name);
+ } else
+ snprintf(c, sizeof(c), "0x%llx",
+ (unsigned long long)pc[i]);
+ /* Allocated by Plookup_by_addr. */
+ free((char *)name);
+ } else if (str != NULL && str[0] != '\0' && str[0] != '@' &&
+ (pid >= 0 &&
+ ((map = dt_Paddr_to_map(dtp, pid, pc[i])) == NULL ||
+ (map->pr_mflags & MA_WRITE)))) {
+ /*
+ * If the current string pointer in the string table
+ * does not point to an empty string _and_ the program
+ * counter falls in a writable region, we'll use the
+ * string from the string table instead of the raw
+ * address. This last condition is necessary because
+ * some (broken) ustack helpers will return a string
+ * even for a program counter that they can't
+ * identify. If we have a string for a program
+ * counter that falls in a segment that isn't
+ * writable, we assume that we have fallen into this
+ * case and we refuse to use the string.
+ */
+ snprintf(c, sizeof(c), "%s", str);
+ } else {
+ if (pid >= 0 && dt_Pobjname(dtp, pid, pc[i], objname,
+ sizeof(objname)) != NULL)
+ snprintf(c, sizeof(c), "%s`0x%llx",
+ dt_basename(objname), (unsigned long long)pc[i]);
+ else
+ snprintf(c, sizeof(c), "0x%llx",
+ (unsigned long long)pc[i]);
+ }
+
+ if ((err = dt_printf(dtp, fp, format, c)) < 0)
+ break;
+
+ if ((err = dt_printf(dtp, fp, "\n")) < 0)
+ break;
+
+ if (str != NULL && str[0] == '@') {
+ /*
+ * If the first character of the string is an "at" sign,
+ * then the string is inferred to be an annotation --
+ * and it is printed out beneath the frame and offset
+ * with brackets.
+ */
+ if ((err = dt_printf(dtp, fp, "%*s", indent, "")) < 0)
+ break;
+
+ snprintf(c, sizeof(c), " [ %s ]", &str[1]);
+
+ if ((err = dt_printf(dtp, fp, format, c)) < 0)
+ break;
+
+ if ((err = dt_printf(dtp, fp, "\n")) < 0)
+ break;
+ }
+
+ if (str != NULL) {
+ str += strlen(str) + 1;
+ if (str - strbase >= strsize)
+ str = NULL;
+ }
+ }
+
+ if (pid >= 0)
+ dt_proc_release_unlock(dtp, pid);
+
+ return err;
+}
+
/*ARGSUSED*/
static int
pfprint_stack(dtrace_hdl_t *dtp, FILE *fp, const char *format,
@@ -381,19 +580,20 @@ pfprint_stack(dtrace_hdl_t *dtp, FILE *fp, const char *format,
uint64_t normal, uint64_t sig)
{
int width;
- dtrace_optval_t saved = dtp->dt_options[DTRACEOPT_STACKINDENT];
const dtrace_recdesc_t *rec = pfd->pfd_rec;
caddr_t addr = (caddr_t)vaddr;
+ uint32_t depth = DTRACE_STACK_NFRAMES(rec->dtrd_arg);
int err = 0;
+ if (depth == 0)
+ return 0;
+
/*
- * We have stashed the value of the STACKINDENT option, and we will
- * now override it for the purposes of formatting the stack. If the
- * field has been specified as left-aligned (i.e. (%-#), we set the
- * indentation to be the width. This is a slightly odd semantic, but
- * it's useful functionality -- and it's slightly odd to begin with to
- * be using a single format specifier to be formatting multiple lines
- * of text...
+ * If the field has been specified as left-aligned (i.e. (%-#), we use
+ * the field width as indentation. This is a slightly odd semantic
+ * but it's useful functionality -- and it's slightly odd to begin with
+ * to be using a single format specifier to be formatting multiple
+ * lines of text...
*/
if (pfd->pfd_dynwidth < 0) {
assert(pfd->pfd_flags & DT_PFCONV_DYNWIDTH);
@@ -404,24 +604,14 @@ pfprint_stack(dtrace_hdl_t *dtp, FILE *fp, const char *format,
width = 0;
}
- dtp->dt_options[DTRACEOPT_STACKINDENT] = width;
-
- switch (rec->dtrd_action) {
- case DTRACEACT_USTACK:
- case DTRACEACT_JSTACK:
- err = dt_print_ustack(dtp, fp, format, addr, rec->dtrd_arg);
- break;
-
- case DTRACEACT_STACK:
- err = dt_print_stack(dtp, fp, format, addr, rec->dtrd_arg,
- rec->dtrd_size / rec->dtrd_arg);
- break;
-
- default:
- assert(0);
- }
+ if (dt_printf(dtp, fp, "\n") < 0)
+ return -1;
- dtp->dt_options[DTRACEOPT_STACKINDENT] = saved;
+ if (DTRACE_STACK_IS_USER(rec->dtrd_arg))
+ err = dt_print_stack_user(dtp, fp, format, addr, width, depth,
+ DTRACE_STACK_STRSIZE(rec->dtrd_arg));
+ else
+ err = dt_print_stack_kernel(dtp, fp, format, addr, width, depth);
return err;
}
@@ -2287,3 +2477,29 @@ dt_print_type(dtrace_hdl_t *dtp, FILE *fp, void *fmtdata,
return 2;
}
+
+int
+dt_print_stack(dtrace_hdl_t *dtp, FILE *fp, void *fmtdata,
+ const dtrace_probedata_t *data, const dtrace_recdesc_t *recs,
+ uint_t nrecs, const void *buf, size_t len)
+{
+ const char *format;
+ dt_pfargd_t pfd;
+
+ if (fmtdata == NULL)
+ format = "%s";
+ else
+ format = ((dt_pfargv_t *)fmtdata)->pfv_format;
+
+ /* pfprint_stack() uses pfd_rec, pfd_flags, and pfd_width only */
+ memset(&pfd, 0, sizeof(pfd));
+ pfd.pfd_rec = recs;
+ pfd.pfd_flags = DT_PFCONV_LEFT;
+
+ if (dtp->dt_options[DTRACEOPT_STACKINDENT] != DTRACEOPT_UNSET)
+ pfd.pfd_width = (int)dtp->dt_options[DTRACEOPT_STACKINDENT];
+ else
+ pfd.pfd_width = _dtrace_stkindent;
+
+ return pfprint_stack(dtp, fp, format, &pfd, data->dtpda_data, 0, 0, 0);
+}
diff --git a/libdtrace/dt_printf.h b/libdtrace/dt_printf.h
index f08e48eb..7a1d0dda 100644
--- a/libdtrace/dt_printf.h
+++ b/libdtrace/dt_printf.h
@@ -102,16 +102,16 @@ extern void dt_printf_validate(dt_pfargv_t *, uint_t,
extern void dt_printa_validate(struct dt_node *, struct dt_node *);
-extern int dt_print_stack(dtrace_hdl_t *, FILE *,
- const char *, caddr_t, int, int);
-extern int dt_print_ustack(dtrace_hdl_t *, FILE *,
- const char *, caddr_t, uint64_t);
extern int dt_print_mod(dtrace_hdl_t *, FILE *, const char *, caddr_t);
extern int dt_print_umod(dtrace_hdl_t *, FILE *, const char *, caddr_t);
extern int dt_print_type(dtrace_hdl_t *dtp, FILE *fp, void *fmtdata,
const dtrace_probedata_t *data,
- const dtrace_recdesc_t *recs,
- uint_t nrecs, const void *buf, size_t len);
+ const dtrace_recdesc_t *recs, uint_t nrecs,
+ const void *buf, size_t len);
+extern int dt_print_stack(dtrace_hdl_t *dtp, FILE *fp, void *fmtdata,
+ const dtrace_probedata_t *data,
+ const dtrace_recdesc_t *recs, uint_t nrecs,
+ const void *buf, size_t len);
#ifdef __cplusplus
}
--
2.43.5
More information about the DTrace-devel
mailing list