@@ -310,16 +310,14 @@ static u32 btf_type_int(const struct btf_type *t)
310
310
return * (u32 * )(t + 1 );
311
311
}
312
312
313
- static const char * type_from_btf_id (struct btf * btf , s32 id )
313
+ static const char * fetch_type_from_btf_type (struct btf * btf ,
314
+ const struct btf_type * type ,
315
+ struct traceprobe_parse_context * ctx )
314
316
{
315
- const struct btf_type * t ;
316
317
u32 intdata ;
317
- s32 tid ;
318
318
319
319
/* TODO: const char * could be converted as a string */
320
- t = btf_type_skip_modifiers (btf , id , & tid );
321
-
322
- switch (BTF_INFO_KIND (t -> info )) {
320
+ switch (BTF_INFO_KIND (type -> info )) {
323
321
case BTF_KIND_ENUM :
324
322
/* enum is "int", so convert to "s32" */
325
323
return "s32" ;
@@ -332,7 +330,7 @@ static const char *type_from_btf_id(struct btf *btf, s32 id)
332
330
else
333
331
return "x32" ;
334
332
case BTF_KIND_INT :
335
- intdata = btf_type_int (t );
333
+ intdata = btf_type_int (type );
336
334
if (BTF_INT_ENCODING (intdata ) & BTF_INT_SIGNED ) {
337
335
switch (BTF_INT_BITS (intdata )) {
338
336
case 8 :
@@ -355,6 +353,10 @@ static const char *type_from_btf_id(struct btf *btf, s32 id)
355
353
case 64 :
356
354
return "u64" ;
357
355
}
356
+ /* bitfield, size is encoded in the type */
357
+ ctx -> last_bitsize = BTF_INT_BITS (intdata );
358
+ ctx -> last_bitoffs += BTF_INT_OFFSET (intdata );
359
+ return "u64" ;
358
360
}
359
361
}
360
362
/* TODO: support other types */
@@ -406,15 +408,136 @@ static void clear_btf_context(struct traceprobe_parse_context *ctx)
406
408
}
407
409
}
408
410
409
- static int parse_btf_arg (const char * varname , struct fetch_insn * code ,
411
+ /* Return 1 if the field separater is arrow operator ('->') */
412
+ static int split_next_field (char * varname , char * * next_field ,
413
+ struct traceprobe_parse_context * ctx )
414
+ {
415
+ char * field ;
416
+ int ret = 0 ;
417
+
418
+ field = strpbrk (varname , ".-" );
419
+ if (field ) {
420
+ if (field [0 ] == '-' && field [1 ] == '>' ) {
421
+ field [0 ] = '\0' ;
422
+ field += 2 ;
423
+ ret = 1 ;
424
+ } else if (field [0 ] == '.' ) {
425
+ field [0 ] = '\0' ;
426
+ field += 1 ;
427
+ } else {
428
+ trace_probe_log_err (ctx -> offset + field - varname , BAD_HYPHEN );
429
+ return - EINVAL ;
430
+ }
431
+ * next_field = field ;
432
+ }
433
+
434
+ return ret ;
435
+ }
436
+
437
+ /*
438
+ * Parse the field of data structure. The @type must be a pointer type
439
+ * pointing the target data structure type.
440
+ */
441
+ static int parse_btf_field (char * fieldname , const struct btf_type * type ,
442
+ struct fetch_insn * * pcode , struct fetch_insn * end ,
443
+ struct traceprobe_parse_context * ctx )
444
+ {
445
+ struct fetch_insn * code = * pcode ;
446
+ const struct btf_member * field ;
447
+ u32 bitoffs , anon_offs ;
448
+ char * next ;
449
+ int is_ptr ;
450
+ s32 tid ;
451
+
452
+ do {
453
+ /* Outer loop for solving arrow operator ('->') */
454
+ if (BTF_INFO_KIND (type -> info ) != BTF_KIND_PTR ) {
455
+ trace_probe_log_err (ctx -> offset , NO_PTR_STRCT );
456
+ return - EINVAL ;
457
+ }
458
+ /* Convert a struct pointer type to a struct type */
459
+ type = btf_type_skip_modifiers (ctx -> btf , type -> type , & tid );
460
+ if (!type ) {
461
+ trace_probe_log_err (ctx -> offset , BAD_BTF_TID );
462
+ return - EINVAL ;
463
+ }
464
+
465
+ bitoffs = 0 ;
466
+ do {
467
+ /* Inner loop for solving dot operator ('.') */
468
+ next = NULL ;
469
+ is_ptr = split_next_field (fieldname , & next , ctx );
470
+ if (is_ptr < 0 )
471
+ return is_ptr ;
472
+
473
+ anon_offs = 0 ;
474
+ field = btf_find_struct_member (ctx -> btf , type , fieldname ,
475
+ & anon_offs );
476
+ if (!field ) {
477
+ trace_probe_log_err (ctx -> offset , NO_BTF_FIELD );
478
+ return - ENOENT ;
479
+ }
480
+ /* Add anonymous structure/union offset */
481
+ bitoffs += anon_offs ;
482
+
483
+ /* Accumulate the bit-offsets of the dot-connected fields */
484
+ if (btf_type_kflag (type )) {
485
+ bitoffs += BTF_MEMBER_BIT_OFFSET (field -> offset );
486
+ ctx -> last_bitsize = BTF_MEMBER_BITFIELD_SIZE (field -> offset );
487
+ } else {
488
+ bitoffs += field -> offset ;
489
+ ctx -> last_bitsize = 0 ;
490
+ }
491
+
492
+ type = btf_type_skip_modifiers (ctx -> btf , field -> type , & tid );
493
+ if (!type ) {
494
+ trace_probe_log_err (ctx -> offset , BAD_BTF_TID );
495
+ return - EINVAL ;
496
+ }
497
+
498
+ ctx -> offset += next - fieldname ;
499
+ fieldname = next ;
500
+ } while (!is_ptr && fieldname );
501
+
502
+ if (++ code == end ) {
503
+ trace_probe_log_err (ctx -> offset , TOO_MANY_OPS );
504
+ return - EINVAL ;
505
+ }
506
+ code -> op = FETCH_OP_DEREF ; /* TODO: user deref support */
507
+ code -> offset = bitoffs / 8 ;
508
+ * pcode = code ;
509
+
510
+ ctx -> last_bitoffs = bitoffs % 8 ;
511
+ ctx -> last_type = type ;
512
+ } while (fieldname );
513
+
514
+ return 0 ;
515
+ }
516
+
517
+ static int parse_btf_arg (char * varname ,
518
+ struct fetch_insn * * pcode , struct fetch_insn * end ,
410
519
struct traceprobe_parse_context * ctx )
411
520
{
521
+ struct fetch_insn * code = * pcode ;
412
522
const struct btf_param * params ;
413
- int i ;
523
+ const struct btf_type * type ;
524
+ char * field = NULL ;
525
+ int i , is_ptr ;
526
+ u32 tid ;
414
527
415
528
if (WARN_ON_ONCE (!ctx -> funcname ))
416
529
return - EINVAL ;
417
530
531
+ is_ptr = split_next_field (varname , & field , ctx );
532
+ if (is_ptr < 0 )
533
+ return is_ptr ;
534
+ if (!is_ptr && field ) {
535
+ /* dot-connected field on an argument is not supported. */
536
+ trace_probe_log_err (ctx -> offset + field - varname ,
537
+ NOSUP_DAT_ARG );
538
+ return - EOPNOTSUPP ;
539
+ }
540
+
418
541
if (!ctx -> params ) {
419
542
params = find_btf_func_param (ctx -> funcname ,
420
543
& ctx -> nr_params , & ctx -> btf ,
@@ -436,24 +559,39 @@ static int parse_btf_arg(const char *varname, struct fetch_insn *code,
436
559
code -> param = i + 1 ;
437
560
else
438
561
code -> param = i ;
439
- return 0 ;
562
+
563
+ tid = params [i ].type ;
564
+ goto found ;
440
565
}
441
566
}
442
567
trace_probe_log_err (ctx -> offset , NO_BTFARG );
443
568
return - ENOENT ;
569
+
570
+ found :
571
+ type = btf_type_skip_modifiers (ctx -> btf , tid , & tid );
572
+ if (!type ) {
573
+ trace_probe_log_err (ctx -> offset , BAD_BTF_TID );
574
+ return - EINVAL ;
575
+ }
576
+ /* Initialize the last type information */
577
+ ctx -> last_type = type ;
578
+ ctx -> last_bitoffs = 0 ;
579
+ ctx -> last_bitsize = 0 ;
580
+ if (field ) {
581
+ ctx -> offset += field - varname ;
582
+ return parse_btf_field (field , type , pcode , end , ctx );
583
+ }
584
+ return 0 ;
444
585
}
445
586
446
- static const struct fetch_type * parse_btf_arg_type (int arg_idx ,
587
+ static const struct fetch_type * parse_btf_arg_type (
447
588
struct traceprobe_parse_context * ctx )
448
589
{
449
590
struct btf * btf = ctx -> btf ;
450
591
const char * typestr = NULL ;
451
592
452
- if (btf && ctx -> params ) {
453
- if (ctx -> flags & TPARG_FL_TPOINT )
454
- arg_idx -- ;
455
- typestr = type_from_btf_id (btf , ctx -> params [arg_idx ].type );
456
- }
593
+ if (btf && ctx -> last_type )
594
+ typestr = fetch_type_from_btf_type (btf , ctx -> last_type , ctx );
457
595
458
596
return find_fetch_type (typestr , ctx -> flags );
459
597
}
@@ -462,21 +600,45 @@ static const struct fetch_type *parse_btf_retval_type(
462
600
struct traceprobe_parse_context * ctx )
463
601
{
464
602
const char * typestr = NULL ;
465
- const struct btf_type * t ;
603
+ const struct btf_type * type ;
466
604
struct btf * btf ;
467
605
468
606
if (ctx -> funcname ) {
469
607
/* Do not use ctx->btf, because it must be used with ctx->param */
470
- t = btf_find_func_proto (ctx -> funcname , & btf );
471
- if (t ) {
472
- typestr = type_from_btf_id (btf , t -> type );
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 );
473
613
btf_put (btf );
474
614
}
475
615
}
476
616
477
617
return find_fetch_type (typestr , ctx -> flags );
478
618
}
479
619
620
+ static int parse_btf_bitfield (struct fetch_insn * * pcode ,
621
+ struct traceprobe_parse_context * ctx )
622
+ {
623
+ struct fetch_insn * code = * pcode ;
624
+
625
+ if ((ctx -> last_bitsize % 8 == 0 ) && ctx -> last_bitoffs == 0 )
626
+ return 0 ;
627
+
628
+ code ++ ;
629
+ if (code -> op != FETCH_OP_NOP ) {
630
+ trace_probe_log_err (ctx -> offset , TOO_MANY_OPS );
631
+ return - EINVAL ;
632
+ }
633
+ * pcode = code ;
634
+
635
+ code -> op = FETCH_OP_MOD_BF ;
636
+ code -> lshift = 64 - (ctx -> last_bitsize + ctx -> last_bitoffs );
637
+ code -> rshift = 64 - ctx -> last_bitsize ;
638
+ code -> basesize = 64 / 8 ;
639
+ return 0 ;
640
+ }
641
+
480
642
static bool is_btf_retval_void (const char * funcname )
481
643
{
482
644
const struct btf_type * t ;
@@ -503,14 +665,22 @@ static const struct btf_param *find_btf_func_param(const char *funcname, s32 *nr
503
665
return ERR_PTR (- EOPNOTSUPP );
504
666
}
505
667
506
- static int parse_btf_arg (const char * varname , struct fetch_insn * code ,
668
+ static int parse_btf_arg (char * varname ,
669
+ struct fetch_insn * * pcode , struct fetch_insn * end ,
507
670
struct traceprobe_parse_context * ctx )
508
671
{
509
672
trace_probe_log_err (ctx -> offset , NOSUP_BTFARG );
510
673
return - EOPNOTSUPP ;
511
674
}
512
675
513
- #define parse_btf_arg_type (idx , ctx ) \
676
+ static int parse_btf_bitfield (struct fetch_insn * * pcode ,
677
+ struct traceprobe_parse_context * ctx )
678
+ {
679
+ trace_probe_log_err (ctx -> offset , NOSUP_BTFARG );
680
+ return - EOPNOTSUPP ;
681
+ }
682
+
683
+ #define parse_btf_arg_type (ctx ) \
514
684
find_fetch_type(NULL, ctx->flags)
515
685
516
686
#define parse_btf_retval_type (ctx ) \
@@ -778,6 +948,8 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
778
948
779
949
code -> op = deref ;
780
950
code -> offset = offset ;
951
+ /* Reset the last type if used */
952
+ ctx -> last_type = NULL ;
781
953
}
782
954
break ;
783
955
case '\\' : /* Immediate value */
@@ -801,7 +973,7 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
801
973
trace_probe_log_err (ctx -> offset , NOSUP_BTFARG );
802
974
return - EINVAL ;
803
975
}
804
- ret = parse_btf_arg (arg , code , ctx );
976
+ ret = parse_btf_arg (arg , pcode , end , ctx );
805
977
break ;
806
978
}
807
979
}
@@ -947,16 +1119,17 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
947
1119
goto out ;
948
1120
code [FETCH_INSN_MAX - 1 ].op = FETCH_OP_END ;
949
1121
1122
+ ctx -> last_type = NULL ;
950
1123
ret = parse_probe_arg (arg , parg -> type , & code , & code [FETCH_INSN_MAX - 1 ],
951
1124
ctx );
952
1125
if (ret )
953
1126
goto fail ;
954
1127
955
1128
/* Update storing type if BTF is available */
956
1129
if (IS_ENABLED (CONFIG_PROBE_EVENTS_BTF_ARGS ) && !t ) {
957
- if (code -> op == FETCH_OP_ARG )
958
- parg -> type = parse_btf_arg_type (code -> param , ctx );
959
- else if (code -> op == FETCH_OP_RETVAL )
1130
+ if (ctx -> last_type )
1131
+ parg -> type = parse_btf_arg_type (ctx );
1132
+ else if (ctx -> flags & TPARG_FL_RETURN )
960
1133
parg -> type = parse_btf_retval_type (ctx );
961
1134
}
962
1135
@@ -1031,6 +1204,11 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
1031
1204
trace_probe_log_err (ctx -> offset + t - arg , BAD_BITFIELD );
1032
1205
goto fail ;
1033
1206
}
1207
+ } else if (IS_ENABLED (CONFIG_PROBE_EVENTS_BTF_ARGS ) &&
1208
+ ctx -> last_type ) {
1209
+ ret = parse_btf_bitfield (& code , ctx );
1210
+ if (ret )
1211
+ goto fail ;
1034
1212
}
1035
1213
ret = - EINVAL ;
1036
1214
/* Loop(Array) operation */
0 commit comments