@@ -364,45 +364,54 @@ static const char *fetch_type_from_btf_type(struct btf *btf,
364364 return NULL ;
365365}
366366
367- static const struct btf_param * find_btf_func_param (const char * funcname , s32 * nr ,
368- struct btf * * btf_p , bool tracepoint )
367+ static int query_btf_context (struct traceprobe_parse_context * ctx )
369368{
370369 const struct btf_param * param ;
371- const struct btf_type * t ;
370+ const struct btf_type * type ;
372371 struct btf * btf ;
372+ s32 nr ;
373373
374- if (! funcname || ! nr )
375- return ERR_PTR ( - EINVAL ) ;
374+ if (ctx -> btf )
375+ return 0 ;
376376
377- t = btf_find_func_proto (funcname , & btf );
378- if (!t )
379- return (const struct btf_param * )t ;
377+ if (!ctx -> funcname )
378+ return - EINVAL ;
380379
381- param = btf_get_func_param ( t , nr );
382- if (IS_ERR_OR_NULL ( param ) )
383- goto err ;
380+ type = btf_find_func_proto ( ctx -> funcname , & btf );
381+ if (! type )
382+ return - ENOENT ;
384383
385- /* Hide the first 'data' argument of tracepoint */
386- if (tracepoint ) {
387- (* nr )-- ;
388- param ++ ;
384+ ctx -> btf = btf ;
385+ ctx -> proto = type ;
386+
387+ /* ctx->params is optional, since func(void) will not have params. */
388+ nr = 0 ;
389+ param = btf_get_func_param (type , & nr );
390+ if (!IS_ERR_OR_NULL (param )) {
391+ /* Hide the first 'data' argument of tracepoint */
392+ if (ctx -> flags & TPARG_FL_TPOINT ) {
393+ nr -- ;
394+ param ++ ;
395+ }
389396 }
390397
391- if (* nr > 0 ) {
392- * btf_p = btf ;
393- return param ;
398+ if (nr > 0 ) {
399+ ctx -> nr_params = nr ;
400+ ctx -> params = param ;
401+ } else {
402+ ctx -> nr_params = 0 ;
403+ ctx -> params = NULL ;
394404 }
395405
396- err :
397- btf_put (btf );
398- return NULL ;
406+ return 0 ;
399407}
400408
401409static void clear_btf_context (struct traceprobe_parse_context * ctx )
402410{
403411 if (ctx -> btf ) {
404412 btf_put (ctx -> btf );
405413 ctx -> btf = NULL ;
414+ ctx -> proto = NULL ;
406415 ctx -> params = NULL ;
407416 ctx -> nr_params = 0 ;
408417 }
@@ -522,7 +531,7 @@ static int parse_btf_arg(char *varname,
522531 const struct btf_param * params ;
523532 const struct btf_type * type ;
524533 char * field = NULL ;
525- int i , is_ptr ;
534+ int i , is_ptr , ret ;
526535 u32 tid ;
527536
528537 if (WARN_ON_ONCE (!ctx -> funcname ))
@@ -538,17 +547,37 @@ static int parse_btf_arg(char *varname,
538547 return - EOPNOTSUPP ;
539548 }
540549
541- if (!ctx -> params ) {
542- params = find_btf_func_param (ctx -> funcname ,
543- & ctx -> nr_params , & ctx -> btf ,
544- ctx -> flags & TPARG_FL_TPOINT );
545- if (IS_ERR_OR_NULL (params )) {
550+ if (ctx -> flags & TPARG_FL_RETURN ) {
551+ if (strcmp (varname , "$retval" ) != 0 ) {
552+ trace_probe_log_err (ctx -> offset , NO_BTFARG );
553+ return - ENOENT ;
554+ }
555+ code -> op = FETCH_OP_RETVAL ;
556+ /* Check whether the function return type is not void */
557+ if (query_btf_context (ctx ) == 0 ) {
558+ if (ctx -> proto -> type == 0 ) {
559+ trace_probe_log_err (ctx -> offset , NO_RETVAL );
560+ return - ENOENT ;
561+ }
562+ tid = ctx -> proto -> type ;
563+ goto found ;
564+ }
565+ if (field ) {
566+ trace_probe_log_err (ctx -> offset + field - varname ,
567+ NO_BTF_ENTRY );
568+ return - ENOENT ;
569+ }
570+ return 0 ;
571+ }
572+
573+ if (!ctx -> btf ) {
574+ ret = query_btf_context (ctx );
575+ if (ret < 0 || ctx -> nr_params == 0 ) {
546576 trace_probe_log_err (ctx -> offset , NO_BTF_ENTRY );
547577 return PTR_ERR (params );
548578 }
549- ctx -> params = params ;
550- } else
551- params = ctx -> params ;
579+ }
580+ params = ctx -> params ;
552581
553582 for (i = 0 ; i < ctx -> nr_params ; i ++ ) {
554583 const char * name = btf_name_by_offset (ctx -> btf , params [i ].name_off );
@@ -559,7 +588,6 @@ static int parse_btf_arg(char *varname,
559588 code -> param = i + 1 ;
560589 else
561590 code -> param = i ;
562-
563591 tid = params [i ].type ;
564592 goto found ;
565593 }
@@ -584,7 +612,7 @@ static int parse_btf_arg(char *varname,
584612 return 0 ;
585613}
586614
587- static const struct fetch_type * parse_btf_arg_type (
615+ static const struct fetch_type * find_fetch_type_from_btf_type (
588616 struct traceprobe_parse_context * ctx )
589617{
590618 struct btf * btf = ctx -> btf ;
@@ -596,27 +624,6 @@ static const struct fetch_type *parse_btf_arg_type(
596624 return find_fetch_type (typestr , ctx -> flags );
597625}
598626
599- static const struct fetch_type * parse_btf_retval_type (
600- struct traceprobe_parse_context * ctx )
601- {
602- const char * typestr = NULL ;
603- const struct btf_type * type ;
604- struct btf * btf ;
605-
606- if (ctx -> funcname ) {
607- /* Do not use ctx->btf, because it must be used with ctx->param */
608- type = btf_find_func_proto (ctx -> funcname , & btf );
609- if (type ) {
610- type = btf_type_skip_modifiers (btf , type -> type , NULL );
611- if (!IS_ERR_OR_NULL (type ))
612- typestr = fetch_type_from_btf_type (btf , type , ctx );
613- btf_put (btf );
614- }
615- }
616-
617- return find_fetch_type (typestr , ctx -> flags );
618- }
619-
620627static int parse_btf_bitfield (struct fetch_insn * * pcode ,
621628 struct traceprobe_parse_context * ctx )
622629{
@@ -639,30 +646,15 @@ static int parse_btf_bitfield(struct fetch_insn **pcode,
639646 return 0 ;
640647}
641648
642- static bool is_btf_retval_void (const char * funcname )
643- {
644- const struct btf_type * t ;
645- struct btf * btf ;
646- bool ret ;
647-
648- t = btf_find_func_proto (funcname , & btf );
649- if (!t )
650- return false;
651-
652- ret = (t -> type == 0 );
653- btf_put (btf );
654- return ret ;
655- }
656649#else
657650static void clear_btf_context (struct traceprobe_parse_context * ctx )
658651{
659652 ctx -> btf = NULL ;
660653}
661654
662- static const struct btf_param * find_btf_func_param (const char * funcname , s32 * nr ,
663- struct btf * * btf_p , bool tracepoint )
655+ static int query_btf_context (struct traceprobe_parse_context * ctx )
664656{
665- return ERR_PTR ( - EOPNOTSUPP ) ;
657+ return - EOPNOTSUPP ;
666658}
667659
668660static int parse_btf_arg (char * varname ,
@@ -680,24 +672,23 @@ static int parse_btf_bitfield(struct fetch_insn **pcode,
680672 return - EOPNOTSUPP ;
681673}
682674
683- #define parse_btf_arg_type (ctx ) \
684- find_fetch_type(NULL, ctx->flags)
685-
686- #define parse_btf_retval_type (ctx ) \
675+ #define find_fetch_type_from_btf_type (ctx ) \
687676 find_fetch_type(NULL, ctx->flags)
688677
689- #define is_btf_retval_void (funcname ) (false)
690-
691678#endif
692679
693680#define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long))
694681
695- static int parse_probe_vars (char * arg , const struct fetch_type * t ,
696- struct fetch_insn * code ,
682+ /* Parse $vars. @orig_arg points '$', which syncs to @ctx->offset */
683+ static int parse_probe_vars (char * orig_arg , const struct fetch_type * t ,
684+ struct fetch_insn * * pcode ,
685+ struct fetch_insn * end ,
697686 struct traceprobe_parse_context * ctx )
698687{
699- unsigned long param ;
688+ struct fetch_insn * code = * pcode ;
700689 int err = TP_ERR_BAD_VAR ;
690+ char * arg = orig_arg + 1 ;
691+ unsigned long param ;
701692 int ret = 0 ;
702693 int len ;
703694
@@ -716,18 +707,17 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t,
716707 goto inval ;
717708 }
718709
719- if (strcmp (arg , "retval" ) == 0 ) {
720- if (ctx -> flags & TPARG_FL_RETURN ) {
721- if (( ctx -> flags & TPARG_FL_KERNEL ) &&
722- is_btf_retval_void ( ctx -> funcname )) {
723- err = TP_ERR_NO_RETVAL ;
724- goto inval ;
725- }
710+ if (str_has_prefix (arg , "retval" )) {
711+ if (!( ctx -> flags & TPARG_FL_RETURN ) ) {
712+ err = TP_ERR_RETVAL_ON_PROBE ;
713+ goto inval ;
714+ }
715+ if (!( ctx -> flags & TPARG_FL_KERNEL ) ||
716+ ! IS_ENABLED ( CONFIG_PROBE_EVENTS_BTF_ARGS )) {
726717 code -> op = FETCH_OP_RETVAL ;
727718 return 0 ;
728719 }
729- err = TP_ERR_RETVAL_ON_PROBE ;
730- goto inval ;
720+ return parse_btf_arg (orig_arg , pcode , end , ctx );
731721 }
732722
733723 len = str_has_prefix (arg , "stack" );
@@ -829,7 +819,7 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
829819
830820 switch (arg [0 ]) {
831821 case '$' :
832- ret = parse_probe_vars (arg + 1 , type , code , ctx );
822+ ret = parse_probe_vars (arg , type , pcode , end , ctx );
833823 break ;
834824
835825 case '%' : /* named register */
@@ -1126,12 +1116,9 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
11261116 goto fail ;
11271117
11281118 /* Update storing type if BTF is available */
1129- if (IS_ENABLED (CONFIG_PROBE_EVENTS_BTF_ARGS ) && !t ) {
1130- if (ctx -> last_type )
1131- parg -> type = parse_btf_arg_type (ctx );
1132- else if (ctx -> flags & TPARG_FL_RETURN )
1133- parg -> type = parse_btf_retval_type (ctx );
1134- }
1119+ if (IS_ENABLED (CONFIG_PROBE_EVENTS_BTF_ARGS ) &&
1120+ !t && ctx -> last_type )
1121+ parg -> type = find_fetch_type_from_btf_type (ctx );
11351122
11361123 ret = - EINVAL ;
11371124 /* Store operation */
@@ -1420,7 +1407,6 @@ const char **traceprobe_expand_meta_args(int argc, const char *argv[],
14201407 const struct btf_param * params = NULL ;
14211408 int i , j , n , used , ret , args_idx = -1 ;
14221409 const char * * new_argv = NULL ;
1423- int nr_params ;
14241410
14251411 ret = argv_has_var_arg (argc , argv , & args_idx , ctx );
14261412 if (ret < 0 )
@@ -1431,9 +1417,8 @@ const char **traceprobe_expand_meta_args(int argc, const char *argv[],
14311417 return NULL ;
14321418 }
14331419
1434- params = find_btf_func_param (ctx -> funcname , & nr_params , & ctx -> btf ,
1435- ctx -> flags & TPARG_FL_TPOINT );
1436- if (IS_ERR_OR_NULL (params )) {
1420+ ret = query_btf_context (ctx );
1421+ if (ret < 0 || ctx -> nr_params == 0 ) {
14371422 if (args_idx != -1 ) {
14381423 /* $arg* requires BTF info */
14391424 trace_probe_log_err (0 , NOSUP_BTFARG );
@@ -1442,8 +1427,6 @@ const char **traceprobe_expand_meta_args(int argc, const char *argv[],
14421427 * new_argc = argc ;
14431428 return NULL ;
14441429 }
1445- ctx -> params = params ;
1446- ctx -> nr_params = nr_params ;
14471430
14481431 if (args_idx >= 0 )
14491432 * new_argc = argc + ctx -> nr_params - 1 ;
@@ -1458,7 +1441,7 @@ const char **traceprobe_expand_meta_args(int argc, const char *argv[],
14581441 for (i = 0 , j = 0 ; i < argc ; i ++ ) {
14591442 trace_probe_log_set_index (i + 2 );
14601443 if (i == args_idx ) {
1461- for (n = 0 ; n < nr_params ; n ++ ) {
1444+ for (n = 0 ; n < ctx -> nr_params ; n ++ ) {
14621445 ret = sprint_nth_btf_arg (n , "" , buf + used ,
14631446 bufsize - used , ctx );
14641447 if (ret < 0 )
0 commit comments