[PATCH 2/2] cg: transition [u]stack() from action to subroutine
Kris Van Hees <[email protected]>
| Newsgroups | dev.linux.lists.dtrace |
|---|---|
| Message-ID | <SJ0PR10MB567238538078DC5066122BECC21DA@SJ0PR10MB5672.namprd10.prod.outlook.com> |
In order to allow [u]stack() to be used in expressions, they must be subroutines. An exception is added to allow them to retain their original behaviour as data recording actions as well. The implementation change requires a new internal type to be defined (dt_stack) to hold stack trace data. This patch does not allow [u]stack() to be used in assignments to variables just yet, but it supports all previous uses of [u]stack(). Additional functionality will be added on top of this. Signed-off-by: Kris Van Hees <[email protected]> --- include/dtrace/dif_defines.h | 4 +- libdtrace/dt_cg.c | 343 ++++++++++++------ libdtrace/dt_open.c | 21 +- libdtrace/dt_options.c | 42 ++- libdtrace/dt_printf.c | 3 +- test/unittest/funcs/tst.subr.d | 11 + .../printa/err.D_PRINTF_ARG_TYPE.stack.r | 2 +- .../printa/err.D_PRINTF_ARG_TYPE.ustack.r | 2 +- 8 files changed, 313 insertions(+), 115 deletions(-) diff --git a/include/dtrace/dif_defines.h b/include/dtrace/dif_defines.h index 9f6e3b55..6e412247 100644 --- a/include/dtrace/dif_defines.h +++ b/include/dtrace/dif_defines.h @@ -210,8 +210,10 @@ #define DIF_SUBR_INET_NTOA6 43 #define DIF_SUBR_D_PATH 44 #define DIF_SUBR_LINK_NTOP 45 +#define DIF_SUBR_STACK 46 +#define DIF_SUBR_USTACK 47 -#define DIF_SUBR_MAX 45 +#define DIF_SUBR_MAX 47 typedef uint32_t dif_instr_t; diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c index 2b81f2e0..3eda5873 100644 --- a/libdtrace/dt_cg.c +++ b/libdtrace/dt_cg.c @@ -3907,33 +3907,42 @@ dt_cg_arglist(dt_ident_t *idp, dt_node_t *args, dt_irlist_t *dlp, longjmp(yypcb->pcb_jmpbuf, EDT_NOTUPREG); /* - * Handle actions that can be used as agg keys. - * If we are not an aggregation, dt_cg_node(dnp, ...) - * will alert us there is a problem. + * Some function calls (actions or subroutines) need special + * handling. */ - if (idp->di_kind == DT_IDENT_AGG && - dnp->dn_kind == DT_NODE_FUNC && - dnp->dn_ident != NULL) - switch (dnp->dn_ident->di_id) { - case DT_ACT_STACK: - case DT_ACT_USTACK: - /* If this is a stack()-like function, we can handle it later. */ - dt_cg_push_stack(BPF_REG_FP, dlp, drp); - continue; - case DT_ACT_JSTACK: - dnerror(dnp, D_UNKNOWN, "jstack() is not implemented (yet)\n"); - /* FIXME: Needs implementation */ - case DT_ACT_SYM: - case DT_ACT_MOD: - case DT_ACT_UADDR: - case DT_ACT_UMOD: - case DT_ACT_USYM: - /* Otherwise, use the action's arg, not its "return value". */ - dt_cg_node(dnp->dn_args, dlp, drp); - dt_cg_push_stack(dnp->dn_args->dn_reg, dlp, drp); - dt_regset_free(drp, dnp->dn_args->dn_reg); - continue; + if (dnp->dn_kind == DT_NODE_FUNC) { + dt_ident_t *fidp = dnp->dn_ident; + + assert(fidp != NULL); + + /* + * For subroutines, stack() and ustack() don't need to + * be evaluated until we fill in the data of the tuple. + */ + if (fidp->di_kind == DT_IDENT_FUNC) { + if (fidp->di_id == DIF_SUBR_STACK || + fidp->di_id == DIF_SUBR_USTACK) { + dt_cg_push_stack(BPF_REG_FP, dlp, drp); + continue; + } + } else if (fidp->di_kind == DT_IDENT_ACTFUNC) { + switch (fidp->di_id) { + case DT_ACT_JSTACK: + dnerror(dnp, D_UNKNOWN, "jstack() is not implemented (yet)\n"); + /* FIXME: Needs implementation */ + case DT_ACT_SYM: + case DT_ACT_MOD: + case DT_ACT_UADDR: + case DT_ACT_UMOD: + case DT_ACT_USYM: + /* Otherwise, use the action's arg, not its "return value". */ + dt_cg_node(dnp->dn_args, dlp, drp); + dt_cg_push_stack(dnp->dn_args->dn_reg, dlp, drp); + dt_regset_free(drp, dnp->dn_args->dn_reg); + continue; + } } + } /* Push the component (pointer or value) onto the tuple stack. */ dt_cg_node(dnp, dlp, drp); @@ -3987,50 +3996,63 @@ empty_args: uint_t nextoff; int is_symmod = 0; - if (dnp->dn_kind == DT_NODE_FUNC && - dnp->dn_ident != NULL) - switch (dnp->dn_ident->di_id) { - case DT_ACT_STACK: - tuplesize = dt_cg_act_stack_sub(yypcb, dnp, treg, tuplesize, DTRACEACT_STACK); - continue; - case DT_ACT_USTACK: - tuplesize = dt_cg_act_stack_sub(yypcb, dnp, treg, tuplesize, DTRACEACT_USTACK); - continue; - case DT_ACT_UADDR: - case DT_ACT_USYM: - case DT_ACT_UMOD: - nextoff = (tuplesize + (8 - 1)) & ~(8 - 1); - if (tuplesize < nextoff) - emit(dlp, BPF_ALU64_IMM(BPF_ADD, treg, nextoff - tuplesize)); - - /* Preface the value with the user process pid. */ - if (dt_regset_xalloc_args(drp) == -1) - longjmp(yypcb->pcb_jmpbuf, EDT_NOREG); - dt_regset_xalloc(drp, BPF_REG_0); - emit(dlp, BPF_CALL_HELPER(BPF_FUNC_get_current_pid_tgid)); - dt_regset_free_args(drp); - emit(dlp, BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32)); - emit(dlp, BPF_STORE(BPF_DW, treg, 0, BPF_REG_0)); - dt_regset_free(drp, BPF_REG_0); - - /* Then store the value. */ - dt_regset_xalloc(drp, BPF_REG_0); - emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, areg, -i * DT_STK_SLOT_SZ)); - emit(dlp, BPF_STORE(BPF_DW, treg, 8, BPF_REG_0)); - dt_regset_free(drp, BPF_REG_0); - - emit(dlp, BPF_ALU64_IMM(BPF_ADD, treg, 16)); - tuplesize = nextoff + 16; - - continue; - case DT_ACT_SYM: - case DT_ACT_MOD: - is_symmod = 1; - size = 8; - dt_regset_xalloc(drp, BPF_REG_0); - emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, areg, -i * DT_STK_SLOT_SZ)); - break; + if (dnp->dn_kind == DT_NODE_FUNC) { + dt_ident_t *fidp = dnp->dn_ident; + + if (fidp->di_kind == DT_IDENT_FUNC) { + switch (fidp->di_id) { + case DIF_SUBR_STACK: + tuplesize = dt_cg_act_stack_sub( + yypcb, dnp, treg, + tuplesize, + DTRACEACT_STACK); + continue; + case DIF_SUBR_USTACK: + tuplesize = dt_cg_act_stack_sub( + yypcb, dnp, treg, + tuplesize, + DTRACEACT_USTACK); + continue; + } + } else if (fidp->di_kind == DT_IDENT_ACTFUNC) { + switch (dnp->dn_ident->di_id) { + case DT_ACT_UADDR: + case DT_ACT_USYM: + case DT_ACT_UMOD: + nextoff = ALIGN(tuplesize, 8); + if (tuplesize < nextoff) + emit(dlp, BPF_ALU64_IMM(BPF_ADD, treg, nextoff - tuplesize)); + + /* Preface the value with the user process pid. */ + if (dt_regset_xalloc_args(drp) == -1) + longjmp(yypcb->pcb_jmpbuf, EDT_NOREG); + dt_regset_xalloc(drp, BPF_REG_0); + emit(dlp, BPF_CALL_HELPER(BPF_FUNC_get_current_pid_tgid)); + dt_regset_free_args(drp); + emit(dlp, BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32)); + emit(dlp, BPF_STORE(BPF_DW, treg, 0, BPF_REG_0)); + dt_regset_free(drp, BPF_REG_0); + + /* Then store the value. */ + dt_regset_xalloc(drp, BPF_REG_0); + emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, areg, -i * DT_STK_SLOT_SZ)); + emit(dlp, BPF_STORE(BPF_DW, treg, 8, BPF_REG_0)); + dt_regset_free(drp, BPF_REG_0); + + emit(dlp, BPF_ALU64_IMM(BPF_ADD, treg, 16)); + tuplesize = nextoff + 16; + + continue; + case DT_ACT_SYM: + case DT_ACT_MOD: + is_symmod = 1; + size = 8; + dt_regset_xalloc(drp, BPF_REG_0); + emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, areg, -i * DT_STK_SLOT_SZ)); + break; + } } + } if (!is_symmod) { dt_node_diftype(dtp, dnp, &t); @@ -6322,6 +6344,84 @@ dt_cg_subr_strchr(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp) TRACE_REGSET(" subr-strchr:End "); } +static void +dt_cg_subr_stack(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp) +{ + dtrace_hdl_t *dtp = yypcb->pcb_hdl; + dt_node_t *size = dnp->dn_args; + dt_node_t asize; + int nframes = dtp->dt_options[DTRACEOPT_MAXFRAMES]; + + TRACE_REGSET(" subr-stack:Begin"); + + if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1) + longjmp(yypcb->pcb_jmpbuf, EDT_NOREG); + + /* + * Allocate enough scratch space to hold the maximum stacktrace size. + * Since dt_cg_subr_alloca_impl() requires a node to be passed for the + * allocation size, one is created here based on the stacktrace size. + */ + asize.dn_op = DT_TOK_INT; + asize.dn_kind = DT_NODE_INT; + asize.dn_value = (size ? size->dn_value : nframes) * sizeof(uint64_t); + dt_cg_node(&asize, dlp, drp); + dt_cg_subr_alloca_impl(dnp, &asize, dlp, drp); + dt_regset_free(drp, asize.dn_reg); + asize.dn_reg = -1; + /* Push the native alloca value to be used as return value. */ + dt_cg_push_stack(dnp->dn_reg, dlp, drp); + /* Turn it into a proper alloca pointer. */ + dt_cg_alloca_ptr(dlp, drp, dnp->dn_reg, dnp->dn_reg); + + /* Call the stack helper function to collect the stack. */ + dt_cg_act_stack_sub(yypcb, dnp, dnp->dn_reg, 0, DTRACEACT_STACK); + + /* Pop the native alloca value as return value. */ + dt_cg_pop_stack(dnp->dn_reg, dlp, drp); + + TRACE_REGSET(" subr-stack:End "); +} + +static void +dt_cg_subr_ustack(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp) +{ + dtrace_hdl_t *dtp = yypcb->pcb_hdl; + dt_node_t *size = dnp->dn_args; + dt_node_t asize; + int nframes = dtp->dt_options[DTRACEOPT_MAXFRAMES]; + + TRACE_REGSET(" subr-ustack:Begin"); + + if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1) + longjmp(yypcb->pcb_jmpbuf, EDT_NOREG); + + /* + * Allocate enough scratch space to hold the maximum stacktrace size. + * Since dt_cg_subr_alloca_impl() requires a node to be passed for the + * allocation size, one is created here based on the stacktrace size. + */ + asize.dn_op = DT_TOK_INT; + asize.dn_kind = DT_NODE_INT; + asize.dn_value = (size ? size->dn_value : nframes) * sizeof(uint64_t); + dt_cg_node(&asize, dlp, drp); + dt_cg_subr_alloca_impl(dnp, &asize, dlp, drp); + dt_regset_free(drp, asize.dn_reg); + asize.dn_reg = -1; + /* Push the native alloca value to be used as return value. */ + dt_cg_push_stack(dnp->dn_reg, dlp, drp); + /* Turn it into a proper alloca pointer. */ + dt_cg_alloca_ptr(dlp, drp, dnp->dn_reg, dnp->dn_reg); + + /* Call the stack helper function to collect the stack. */ + dt_cg_act_stack_sub(yypcb, dnp, dnp->dn_reg, 0, DTRACEACT_USTACK); + + /* Pop the native alloca value as return value. */ + dt_cg_pop_stack(dnp->dn_reg, dlp, drp); + + TRACE_REGSET(" subr-ustack:End "); +} + static void dt_cg_subr_strrchr(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp) { @@ -6951,6 +7051,8 @@ static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = { [DIF_SUBR_INET_NTOA6] = &dt_cg_subr_inet_ntoa6, [DIF_SUBR_D_PATH] = &dt_cg_subr_d_path, [DIF_SUBR_LINK_NTOP] = &dt_cg_subr_link_ntop, + [DIF_SUBR_STACK] = &dt_cg_subr_stack, + [DIF_SUBR_USTACK] = &dt_cg_subr_ustack, }; static void @@ -6968,6 +7070,7 @@ dt_cg_call_subr(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp) assert(idp->di_id <= DIF_SUBR_MAX); fun = _dt_cg_subr[idp->di_id]; +assert(fun != NULL); if (fun == NULL) dnerror(dnp, D_FUNC_UNDEF, "unimplemented subroutine: %s\n", idp->di_name); @@ -8690,43 +8793,50 @@ dt_cg_agg(dt_pcb_t *pcb, dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp) uint64_t arg = 0; dt_ident_t *idp = knp->dn_ident; - if (knp->dn_kind == DT_NODE_FUNC && idp != NULL && - idp->di_kind == DT_IDENT_ACTFUNC) { - size = 16; + if (knp->dn_kind == DT_NODE_FUNC && idp != NULL) { alignment = 8; - switch (idp->di_id) { - case DT_ACT_USTACK: - arg = dt_cg_stack_arg(dtp, knp, DTRACEACT_USTACK); - kind = DTRACEACT_USTACK; - size = 8 + 8 * DTRACE_STACK_NFRAMES(arg); - break; - case DT_ACT_JSTACK: - kind = DTRACEACT_JSTACK; - break; - case DT_ACT_USYM: - kind = DTRACEACT_USYM; - break; - case DT_ACT_UMOD: - kind = DTRACEACT_UMOD; - break; - case DT_ACT_UADDR: - kind = DTRACEACT_UADDR; - break; - case DT_ACT_STACK: - arg = dt_cg_stack_arg(dtp, knp, DTRACEACT_STACK); - kind = DTRACEACT_STACK; - size = 8 * arg; - break; - case DT_ACT_SYM: - kind = DTRACEACT_SYM; - size = 8; - break; - case DT_ACT_MOD: - kind = DTRACEACT_MOD; - size = 8; - break; + + if (idp->di_kind == DT_IDENT_FUNC) { + switch (idp->di_id) { + case DIF_SUBR_USTACK: + arg = dt_cg_stack_arg(dtp, knp, DTRACEACT_USTACK); + kind = DTRACEACT_USTACK; + size = 8 + 8 * DTRACE_STACK_NFRAMES(arg); + goto add_rec; + case DIF_SUBR_STACK: + arg = dt_cg_stack_arg(dtp, knp, DTRACEACT_STACK); + kind = DTRACEACT_STACK; + size = 8 * arg; + goto add_rec; + } + } else if (idp->di_kind == DT_IDENT_ACTFUNC) { + size = 16; + switch (idp->di_id) { + case DT_ACT_JSTACK: + kind = DTRACEACT_JSTACK; + goto add_rec; + case DT_ACT_USYM: + kind = DTRACEACT_USYM; + goto add_rec; + case DT_ACT_UMOD: + kind = DTRACEACT_UMOD; + goto add_rec; + case DT_ACT_UADDR: + kind = DTRACEACT_UADDR; + goto add_rec; + case DT_ACT_SYM: + kind = DTRACEACT_SYM; + size = 8; + goto add_rec; + case DT_ACT_MOD: + kind = DTRACEACT_MOD; + size = 8; + goto add_rec; + } } - } else if (dt_node_is_string(knp)) { + } + + if (dt_node_is_string(knp)) { size = dtp->dt_options[DTRACEOPT_STRSIZE] + 1; alignment = 1; } else { @@ -8737,6 +8847,7 @@ dt_cg_agg(dt_pcb_t *pcb, dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp) alignment = size; } +add_rec: dt_aggid_rec_add(dtp, aid->di_id, kind, size, alignment, arg); } } @@ -8820,10 +8931,34 @@ dt_cg(dt_pcb_t *pcb, dt_node_t *dnp) if (enp->dn_kind == DT_NODE_AGG) dt_cg_agg(pcb, enp, &pcb->pcb_ir, pcb->pcb_regs); - else + else { + /* + * Special case: [u]stack() in statement + * context is treated as data generating + * action. + */ + if (enp->dn_kind == DT_NODE_FUNC) { + uint_t id; + + id = enp->dn_ident->di_id; + if (id == DIF_SUBR_STACK) + id = DTRACEACT_STACK; + else if (id == DIF_SUBR_USTACK) + id = DTRACEACT_USTACK; + else + id = 0; + + if (id) { + dt_cg_act_stack(pcb, enp, id); + pcb->pcb_stmt->dtsd_clauseflags |= DT_CLSFLAG_DATAREC; + goto done; + } + } dt_cg_node(enp, &pcb->pcb_ir, pcb->pcb_regs); + } +done: if (enp->dn_reg != -1) { dt_regset_free(pcb->pcb_regs, enp->dn_reg); diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c index 509f263d..9dd8956d 100644 --- a/libdtrace/dt_open.c +++ b/libdtrace/dt_open.c @@ -175,7 +175,7 @@ static const dt_ident_t _dtrace_globals[] = { { "ipl", DT_IDENT_SCALAR, 0, DIF_VAR_IPL, DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "uint_t" }, { "jstack", DT_IDENT_ACTFUNC, 0, DT_ACT_JSTACK, DT_ATTR_STABCMN, DT_VERS_1_0, - &dt_idops_func, "stack([uint32_t], [uint32_t])" }, + &dt_idops_func, "dt_stack([uint32_t], [uint32_t])" }, { "link_ntop", DT_IDENT_FUNC, 0, DIF_SUBR_LINK_NTOP, DT_ATTR_STABCMN, DT_VERS_1_5, &dt_idops_func, "string(int, void *)" }, { "llquantize", DT_IDENT_AGGFUNC, 0, DT_AGG_LLQUANTIZE, @@ -273,8 +273,8 @@ static const dt_ident_t _dtrace_globals[] = { { "speculation", DT_IDENT_FUNC, 0, DIF_SUBR_SPECULATION, DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_func, "int()" }, -{ "stack", DT_IDENT_ACTFUNC, 0, DT_ACT_STACK, DT_ATTR_STABCMN, DT_VERS_1_0, - &dt_idops_func, "stack([uint32_t])" }, +{ "stack", DT_IDENT_FUNC, DT_IDFLG_ALLOCA, DIF_SUBR_STACK, DT_ATTR_STABCMN, + DT_VERS_1_0, &dt_idops_func, "dt_stack([uint32_t])" }, { "stackdepth", DT_IDENT_SCALAR, 0, DIF_VAR_STACKDEPTH, DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "uint32_t" }, @@ -328,8 +328,8 @@ static const dt_ident_t _dtrace_globals[] = { DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" }, { "uregs", DT_IDENT_ARRAY, 0, DIF_VAR_UREGS, DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_regs, NULL }, -{ "ustack", DT_IDENT_ACTFUNC, 0, DT_ACT_USTACK, DT_ATTR_STABCMN, DT_VERS_1_0, - &dt_idops_func, "stack([uint32_t], [uint32_t])" }, +{ "ustack", DT_IDENT_FUNC, DT_IDFLG_ALLOCA, DIF_SUBR_USTACK, DT_ATTR_STABCMN, + DT_VERS_1_0, &dt_idops_func, "dt_stack([uint32_t], [uint32_t])" }, { "ustackdepth", DT_IDENT_SCALAR, 0, DIF_VAR_USTACKDEPTH, DT_ATTR_STABCMN, DT_VERS_1_2, &dt_idops_type, "uint32_t" }, @@ -1054,8 +1054,17 @@ dt_vopen(int version, int flags, int *errp, dtp->dt_type_dyn = ctf_add_typedef(dmp->dm_ctfp, CTF_ADD_ROOT, "<DYN>", ctf_lookup_by_name(dmp->dm_ctfp, "void")); + /* + * The stack type is added as a typedef of uint64_t[MAXFRAMES]. The + * final value of MAXFRAMES may be adjusted with the "stackframes" + * option. + */ + ctr.ctr_contents = ctf_lookup_by_name(dmp->dm_ctfp, "uint64_t"); + ctr.ctr_index = ctf_lookup_by_name(dmp->dm_ctfp, "long"); + ctr.ctr_nelems = _dtrace_stackframes; + dtp->dt_type_stack = ctf_add_typedef(dmp->dm_ctfp, CTF_ADD_ROOT, - "stack", ctf_lookup_by_name(dmp->dm_ctfp, "void")); + "dt_stack", ctf_add_array(dmp->dm_ctfp, CTF_ADD_ROOT, &ctr)); dtp->dt_type_symaddr = ctf_add_typedef(dmp->dm_ctfp, CTF_ADD_ROOT, "_symaddr", ctf_lookup_by_name(dmp->dm_ctfp, "void")); diff --git a/libdtrace/dt_options.c b/libdtrace/dt_options.c index 25e79979..69667f5b 100644 --- a/libdtrace/dt_options.c +++ b/libdtrace/dt_options.c @@ -912,6 +912,46 @@ dt_opt_rate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) return 0; } +/* + * When setting the maxframes option, set the option in the dt_options array + * using dt_opt_runtime() as usual, and then update the definition of the CTF + * type for "_stack" to be an array of the corresponding size. + * If any errors occur, reset dt_options[option] to its previous value. + */ +static int +dt_opt_maxframes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) +{ + dtrace_optval_t val = dtp->dt_options[option]; + ctf_file_t *fp = DT_STACK_CTFP(dtp); + ctf_id_t type = ctf_type_resolve(fp, DT_STACK_TYPE(dtp)); + ctf_arinfo_t r; + + if (dt_opt_runtime(dtp, arg, option) != 0) + return -1; /* dt_errno is set for us */ + + if (dtp->dt_options[option] > UINT_MAX) { + dtp->dt_options[option] = val; + return dt_set_errno(dtp, EOVERFLOW); + } + + if (ctf_array_info(fp, type, &r) == CTF_ERR) { + dtp->dt_options[option] = val; + dtp->dt_ctferr = ctf_errno(fp); + return dt_set_errno(dtp, EDT_CTF); + } + + r.ctr_nelems = (uint_t)dtp->dt_options[option]; + + if (ctf_set_array(fp, type, &r) == CTF_ERR || + ctf_update(fp) == CTF_ERR) { + dtp->dt_options[option] = val; + dtp->dt_ctferr = ctf_errno(fp); + return dt_set_errno(dtp, EDT_CTF); + } + + return 0; +} + /* * When setting the strsize option, set the option in the dt_options array * using dt_opt_size() as usual, and then update the definition of the CTF @@ -1157,7 +1197,7 @@ static const dt_option_t _dtrace_rtoptions[] = { { "jstackframes", dt_opt_runtime, DTRACEOPT_JSTACKFRAMES }, { "jstackstrsize", dt_opt_size, DTRACEOPT_JSTACKSTRSIZE }, { "lockmem", dt_opt_lockmem, DTRACEOPT_LOCKMEM }, - { "maxframes", dt_opt_runtime, DTRACEOPT_MAXFRAMES }, + { "maxframes", dt_opt_maxframes, DTRACEOPT_MAXFRAMES }, { "nusdtprobes", dt_opt_runtime, DTRACEOPT_NUSDTPROBES }, { "nspec", dt_opt_runtime, DTRACEOPT_NSPEC }, { "pcapsize", dt_opt_pcapsize, DTRACEOPT_PCAPSIZE }, diff --git a/libdtrace/dt_printf.c b/libdtrace/dt_printf.c index 4c276c26..06c86a37 100644 --- a/libdtrace/dt_printf.c +++ b/libdtrace/dt_printf.c @@ -24,7 +24,8 @@ static int pfcheck_addr(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) { - return dt_node_is_pointer(dnp) || dt_node_is_integer(dnp); + return (dt_node_is_pointer(dnp) && !dt_node_is_stack(dnp)) || + dt_node_is_integer(dnp); } /*ARGSUSED*/ diff --git a/test/unittest/funcs/tst.subr.d b/test/unittest/funcs/tst.subr.d index 9f7203c0..20e38341 100644 --- a/test/unittest/funcs/tst.subr.d +++ b/test/unittest/funcs/tst.subr.d @@ -36,6 +36,15 @@ /*DSTYLED*/ \ } +#define STKFUNC(x) \ + BEGIN \ + /*DSTYLED*/ \ + { \ + subr++; \ + @stk[x] = sum(1); \ + /*DSTYLED*/ \ + } + #define NUM_UNIMPLEMENTED 7 INTFUNC(rand()) @@ -89,6 +98,8 @@ STRFUNC(inet_ntoa6((in6_addr_t *)alloca(sizeof(in6_addr_t)))) /* Not implemented yet. STRFUNC(d_path(&(curthread->fs->root))) STRFUNC(link_ntop(ARPHRD_ETHER, (void *)alloca(sizeof(ipaddr_t)))) */ +STKFUNC(stack(5)) +STKFUNC(ustack(5)) BEGIN /subr == DIF_SUBR_MAX + 1 - NUM_UNIMPLEMENTED/ diff --git a/test/unittest/printa/err.D_PRINTF_ARG_TYPE.stack.r b/test/unittest/printa/err.D_PRINTF_ARG_TYPE.stack.r index 50e884a0..95ac80da 100644 --- a/test/unittest/printa/err.D_PRINTF_ARG_TYPE.stack.r +++ b/test/unittest/printa/err.D_PRINTF_ARG_TYPE.stack.r @@ -2,4 +2,4 @@ dtrace: failed to compile script test/unittest/printa/err.D_PRINTF_ARG_TYPE.stack.d: [D_PRINTF_ARG_TYPE] line 12: printa( ) argument #2 is incompatible with conversion #1 prototype: conversion: %p prototype: pointer or integer - argument: stack + argument: dt_stack diff --git a/test/unittest/printa/err.D_PRINTF_ARG_TYPE.ustack.r b/test/unittest/printa/err.D_PRINTF_ARG_TYPE.ustack.r index fc9e1512..5df10376 100644 --- a/test/unittest/printa/err.D_PRINTF_ARG_TYPE.ustack.r +++ b/test/unittest/printa/err.D_PRINTF_ARG_TYPE.ustack.r @@ -2,4 +2,4 @@ dtrace: failed to compile script test/unittest/printa/err.D_PRINTF_ARG_TYPE.ustack.d: [D_PRINTF_ARG_TYPE] line 12: printa( ) argument #2 is incompatible with conversion #1 prototype: conversion: %p prototype: pointer or integer - argument: stack + argument: dt_stack -- 2.43.5