Skip to content

Commit fd26290

Browse files
committed
tracing/probes: Add BTF retval type support
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 ^ Link: https://lore.kernel.org/all/168507476195.913472.16290308831790216609.stgit@mhiramat.roam.corp.google.com/ Signed-off-by: Masami Hiramatsu (Google) <[email protected]>
1 parent 18b1e87 commit fd26290

File tree

2 files changed

+63
-7
lines changed

2 files changed

+63
-7
lines changed

kernel/trace/trace_probe.c

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -371,15 +371,13 @@ static const char *type_from_btf_id(struct btf *btf, s32 id)
371371
return NULL;
372372
}
373373

374-
static const struct btf_param *find_btf_func_param(const char *funcname, s32 *nr,
375-
bool tracepoint)
374+
static const struct btf_type *find_btf_func_proto(const char *funcname)
376375
{
377376
struct btf *btf = traceprobe_get_btf();
378-
const struct btf_param *param;
379377
const struct btf_type *t;
380378
s32 id;
381379

382-
if (!btf || !funcname || !nr)
380+
if (!btf || !funcname)
383381
return ERR_PTR(-EINVAL);
384382

385383
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
396394
if (!btf_type_is_func_proto(t))
397395
return ERR_PTR(-ENOENT);
398396

397+
return t;
398+
}
399+
400+
static const struct btf_param *find_btf_func_param(const char *funcname, s32 *nr,
401+
bool tracepoint)
402+
{
403+
const struct btf_param *param;
404+
const struct btf_type *t;
405+
406+
if (!funcname || !nr)
407+
return ERR_PTR(-EINVAL);
408+
409+
t = find_btf_func_proto(funcname);
410+
if (IS_ERR(t))
411+
return (const struct btf_param *)t;
412+
399413
*nr = btf_type_vlen(t);
400414
param = (const struct btf_param *)(t + 1);
401415

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

479+
static const struct fetch_type *parse_btf_retval_type(
480+
struct traceprobe_parse_context *ctx)
481+
{
482+
struct btf *btf = traceprobe_get_btf();
483+
const char *typestr = NULL;
484+
const struct btf_type *t;
485+
486+
if (btf && ctx->funcname) {
487+
t = find_btf_func_proto(ctx->funcname);
488+
if (!IS_ERR(t))
489+
typestr = type_from_btf_id(btf, t->type);
490+
}
491+
492+
return find_fetch_type(typestr, ctx->flags);
493+
}
494+
495+
static bool is_btf_retval_void(const char *funcname)
496+
{
497+
const struct btf_type *t;
498+
499+
t = find_btf_func_proto(funcname);
500+
if (IS_ERR(t))
501+
return false;
502+
503+
return t->type == 0;
504+
}
465505
#else
466506
static struct btf *traceprobe_get_btf(void)
467507
{
@@ -480,8 +520,15 @@ static int parse_btf_arg(const char *varname, struct fetch_insn *code,
480520
trace_probe_log_err(ctx->offset, NOSUP_BTFARG);
481521
return -EOPNOTSUPP;
482522
}
523+
483524
#define parse_btf_arg_type(idx, ctx) \
484525
find_fetch_type(NULL, ctx->flags)
526+
527+
#define parse_btf_retval_type(ctx) \
528+
find_fetch_type(NULL, ctx->flags)
529+
530+
#define is_btf_retval_void(funcname) (false)
531+
485532
#endif
486533

487534
#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,
512559

513560
if (strcmp(arg, "retval") == 0) {
514561
if (ctx->flags & TPARG_FL_RETURN) {
562+
if ((ctx->flags & TPARG_FL_KERNEL) &&
563+
is_btf_retval_void(ctx->funcname)) {
564+
err = TP_ERR_NO_RETVAL;
565+
goto inval;
566+
}
515567
code->op = FETCH_OP_RETVAL;
516568
return 0;
517569
}
@@ -912,9 +964,12 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
912964
goto fail;
913965

914966
/* Update storing type if BTF is available */
915-
if (IS_ENABLED(CONFIG_PROBE_EVENTS_BTF_ARGS) &&
916-
!t && code->op == FETCH_OP_ARG)
917-
parg->type = parse_btf_arg_type(code->param, ctx);
967+
if (IS_ENABLED(CONFIG_PROBE_EVENTS_BTF_ARGS) && !t) {
968+
if (code->op == FETCH_OP_ARG)
969+
parg->type = parse_btf_arg_type(code->param, ctx);
970+
else if (code->op == FETCH_OP_RETVAL)
971+
parg->type = parse_btf_retval_type(ctx);
972+
}
918973

919974
ret = -EINVAL;
920975
/* Store operation */

kernel/trace/trace_probe.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call,
449449
C(BAD_EVENT_NAME, "Event name must follow the same rules as C identifiers"), \
450450
C(EVENT_EXIST, "Given group/event name is already used by another event"), \
451451
C(RETVAL_ON_PROBE, "$retval is not available on probe"), \
452+
C(NO_RETVAL, "This function returns 'void' type"), \
452453
C(BAD_STACK_NUM, "Invalid stack number"), \
453454
C(BAD_ARG_NUM, "Invalid argument number"), \
454455
C(BAD_VAR, "Invalid $-valiable specified"), \

0 commit comments

Comments
 (0)