lkml.org 
[lkml]   [2023]   [May]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v13 09/12] tracing/probes: Add BTF retval type support
    Date
    From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

    Check the target function has non-void retval type and set the correct
    fetch type if user doesn't specify it.
    If the function returns void, $retval is rejected as below;

    # echo 'f unregister_kprobes%return $retval' >> dynamic_events
    sh: write error: No such file or directory
    # cat error_log
    [ 37.488397] trace_fprobe: error: This function returns 'void' type
    Command: f unregister_kprobes%return $retval
    ^

    Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
    ---
    Changes in v8:
    - Fix wrong indentation.
    Changes in v7:
    - Introduce this as a new patch.
    ---
    kernel/trace/trace_probe.c | 69 ++++++++++++++++++++++++++++++++++++++++----
    kernel/trace/trace_probe.h | 1 +
    2 files changed, 63 insertions(+), 7 deletions(-)

    diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
    index 7318642aceb3..dfe3e1823eec 100644
    --- a/kernel/trace/trace_probe.c
    +++ b/kernel/trace/trace_probe.c
    @@ -371,15 +371,13 @@ static const char *type_from_btf_id(struct btf *btf, s32 id)
    return NULL;
    }

    -static const struct btf_param *find_btf_func_param(const char *funcname, s32 *nr,
    - bool tracepoint)
    +static const struct btf_type *find_btf_func_proto(const char *funcname)
    {
    struct btf *btf = traceprobe_get_btf();
    - const struct btf_param *param;
    const struct btf_type *t;
    s32 id;

    - if (!btf || !funcname || !nr)
    + if (!btf || !funcname)
    return ERR_PTR(-EINVAL);

    id = btf_find_by_name_kind(btf, funcname, BTF_KIND_FUNC);
    @@ -396,6 +394,22 @@ static const struct btf_param *find_btf_func_param(const char *funcname, s32 *nr
    if (!btf_type_is_func_proto(t))
    return ERR_PTR(-ENOENT);

    + return t;
    +}
    +
    +static const struct btf_param *find_btf_func_param(const char *funcname, s32 *nr,
    + bool tracepoint)
    +{
    + const struct btf_param *param;
    + const struct btf_type *t;
    +
    + if (!funcname || !nr)
    + return ERR_PTR(-EINVAL);
    +
    + t = find_btf_func_proto(funcname);
    + if (IS_ERR(t))
    + return (const struct btf_param *)t;
    +
    *nr = btf_type_vlen(t);
    param = (const struct btf_param *)(t + 1);

    @@ -462,6 +476,32 @@ static const struct fetch_type *parse_btf_arg_type(int arg_idx,
    return find_fetch_type(typestr, ctx->flags);
    }

    +static const struct fetch_type *parse_btf_retval_type(
    + struct traceprobe_parse_context *ctx)
    +{
    + struct btf *btf = traceprobe_get_btf();
    + const char *typestr = NULL;
    + const struct btf_type *t;
    +
    + if (btf && ctx->funcname) {
    + t = find_btf_func_proto(ctx->funcname);
    + if (!IS_ERR(t))
    + typestr = type_from_btf_id(btf, t->type);
    + }
    +
    + return find_fetch_type(typestr, ctx->flags);
    +}
    +
    +static bool is_btf_retval_void(const char *funcname)
    +{
    + const struct btf_type *t;
    +
    + t = find_btf_func_proto(funcname);
    + if (IS_ERR(t))
    + return false;
    +
    + return t->type == 0;
    +}
    #else
    static struct btf *traceprobe_get_btf(void)
    {
    @@ -480,8 +520,15 @@ static int parse_btf_arg(const char *varname, struct fetch_insn *code,
    trace_probe_log_err(ctx->offset, NOSUP_BTFARG);
    return -EOPNOTSUPP;
    }
    +
    #define parse_btf_arg_type(idx, ctx) \
    find_fetch_type(NULL, ctx->flags)
    +
    +#define parse_btf_retval_type(ctx) \
    + find_fetch_type(NULL, ctx->flags)
    +
    +#define is_btf_retval_void(funcname) (false)
    +
    #endif

    #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long))
    @@ -512,6 +559,11 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t,

    if (strcmp(arg, "retval") == 0) {
    if (ctx->flags & TPARG_FL_RETURN) {
    + if ((ctx->flags & TPARG_FL_KERNEL) &&
    + is_btf_retval_void(ctx->funcname)) {
    + err = TP_ERR_NO_RETVAL;
    + goto inval;
    + }
    code->op = FETCH_OP_RETVAL;
    return 0;
    }
    @@ -912,9 +964,12 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
    goto fail;

    /* Update storing type if BTF is available */
    - if (IS_ENABLED(CONFIG_PROBE_EVENTS_BTF_ARGS) &&
    - !t && code->op == FETCH_OP_ARG)
    - parg->type = parse_btf_arg_type(code->param, ctx);
    + if (IS_ENABLED(CONFIG_PROBE_EVENTS_BTF_ARGS) && !t) {
    + if (code->op == FETCH_OP_ARG)
    + parg->type = parse_btf_arg_type(code->param, ctx);
    + else if (code->op == FETCH_OP_RETVAL)
    + parg->type = parse_btf_retval_type(ctx);
    + }

    ret = -EINVAL;
    /* Store operation */
    diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h
    index c864e6dea10f..eb43bea5c168 100644
    --- a/kernel/trace/trace_probe.h
    +++ b/kernel/trace/trace_probe.h
    @@ -449,6 +449,7 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call,
    C(BAD_EVENT_NAME, "Event name must follow the same rules as C identifiers"), \
    C(EVENT_EXIST, "Given group/event name is already used by another event"), \
    C(RETVAL_ON_PROBE, "$retval is not available on probe"), \
    + C(NO_RETVAL, "This function returns 'void' type"), \
    C(BAD_STACK_NUM, "Invalid stack number"), \
    C(BAD_ARG_NUM, "Invalid argument number"), \
    C(BAD_VAR, "Invalid $-valiable specified"), \
    \
     
     \ /
      Last update: 2023-05-26 06:21    [W:3.351 / U:0.576 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site