@@ -341,9 +341,9 @@ static int __parse_bitfield_probe_arg(const char *bf,
341
341
int traceprobe_parse_probe_arg (char * arg , ssize_t * size ,
342
342
struct probe_arg * parg , bool is_return , bool is_kprobe )
343
343
{
344
- struct fetch_insn * code , * tmp = NULL ;
345
- const char * t ;
346
- int ret ;
344
+ struct fetch_insn * code , * scode , * tmp = NULL ;
345
+ char * t , * t2 ;
346
+ int ret , len ;
347
347
348
348
if (strlen (arg ) > MAX_ARGSTR_LEN ) {
349
349
pr_info ("Argument is too long.: %s\n" , arg );
@@ -354,24 +354,42 @@ int traceprobe_parse_probe_arg(char *arg, ssize_t *size,
354
354
pr_info ("Failed to allocate memory for command '%s'.\n" , arg );
355
355
return - ENOMEM ;
356
356
}
357
- t = strchr (parg -> comm , ':' );
357
+ t = strchr (arg , ':' );
358
358
if (t ) {
359
- arg [t - parg -> comm ] = '\0' ;
360
- t ++ ;
359
+ * t = '\0' ;
360
+ t2 = strchr (++ t , '[' );
361
+ if (t2 ) {
362
+ * t2 = '\0' ;
363
+ parg -> count = simple_strtoul (t2 + 1 , & t2 , 0 );
364
+ if (strcmp (t2 , "]" ) || parg -> count == 0 )
365
+ return - EINVAL ;
366
+ if (parg -> count > MAX_ARRAY_LEN )
367
+ return - E2BIG ;
368
+ }
361
369
}
362
370
/*
363
371
* The default type of $comm should be "string", and it can't be
364
372
* dereferenced.
365
373
*/
366
374
if (!t && strcmp (arg , "$comm" ) == 0 )
367
- t = "string" ;
368
- parg -> type = find_fetch_type (t );
375
+ parg -> type = find_fetch_type ("string" );
376
+ else
377
+ parg -> type = find_fetch_type (t );
369
378
if (!parg -> type ) {
370
379
pr_info ("Unsupported type: %s\n" , t );
371
380
return - EINVAL ;
372
381
}
373
382
parg -> offset = * size ;
374
- * size += parg -> type -> size ;
383
+ * size += parg -> type -> size * (parg -> count ?: 1 );
384
+
385
+ if (parg -> count ) {
386
+ len = strlen (parg -> type -> fmttype ) + 6 ;
387
+ parg -> fmt = kmalloc (len , GFP_KERNEL );
388
+ if (!parg -> fmt )
389
+ return - ENOMEM ;
390
+ snprintf (parg -> fmt , len , "%s[%d]" , parg -> type -> fmttype ,
391
+ parg -> count );
392
+ }
375
393
376
394
code = tmp = kzalloc (sizeof (* code ) * FETCH_INSN_MAX , GFP_KERNEL );
377
395
if (!code )
@@ -391,10 +409,20 @@ int traceprobe_parse_probe_arg(char *arg, ssize_t *size,
391
409
ret = - EINVAL ;
392
410
goto fail ;
393
411
}
394
- /* Since IMM or COMM must be the 1st insn, this is safe */
395
- if (code -> op == FETCH_OP_IMM || code -> op == FETCH_OP_COMM )
412
+ if (code -> op != FETCH_OP_DEREF || parg -> count ) {
413
+ /*
414
+ * IMM and COMM is pointing actual address, those must
415
+ * be kept, and if parg->count != 0, this is an array
416
+ * of string pointers instead of string address itself.
417
+ */
396
418
code ++ ;
419
+ if (code -> op != FETCH_OP_NOP ) {
420
+ ret = - E2BIG ;
421
+ goto fail ;
422
+ }
423
+ }
397
424
code -> op = FETCH_OP_ST_STRING ; /* In DEREF case, replace it */
425
+ code -> size = parg -> type -> size ;
398
426
parg -> dynamic = true;
399
427
} else if (code -> op == FETCH_OP_DEREF ) {
400
428
code -> op = FETCH_OP_ST_MEM ;
@@ -408,12 +436,29 @@ int traceprobe_parse_probe_arg(char *arg, ssize_t *size,
408
436
code -> op = FETCH_OP_ST_RAW ;
409
437
code -> size = parg -> type -> size ;
410
438
}
439
+ scode = code ;
411
440
/* Modify operation */
412
441
if (t != NULL ) {
413
442
ret = __parse_bitfield_probe_arg (t , parg -> type , & code );
414
443
if (ret )
415
444
goto fail ;
416
445
}
446
+ /* Loop(Array) operation */
447
+ if (parg -> count ) {
448
+ if (scode -> op != FETCH_OP_ST_MEM &&
449
+ scode -> op != FETCH_OP_ST_STRING ) {
450
+ pr_info ("array only accepts memory or address\n" );
451
+ ret = - EINVAL ;
452
+ goto fail ;
453
+ }
454
+ code ++ ;
455
+ if (code -> op != FETCH_OP_NOP ) {
456
+ ret = - E2BIG ;
457
+ goto fail ;
458
+ }
459
+ code -> op = FETCH_OP_LP_ARRAY ;
460
+ code -> param = parg -> count ;
461
+ }
417
462
code ++ ;
418
463
code -> op = FETCH_OP_END ;
419
464
@@ -452,14 +497,17 @@ void traceprobe_free_probe_arg(struct probe_arg *arg)
452
497
kfree (arg -> code );
453
498
kfree (arg -> name );
454
499
kfree (arg -> comm );
500
+ kfree (arg -> fmt );
455
501
}
456
502
503
+ /* When len=0, we just calculate the needed length */
504
+ #define LEN_OR_ZERO (len ? len - pos : 0)
457
505
static int __set_print_fmt (struct trace_probe * tp , char * buf , int len ,
458
506
bool is_return )
459
507
{
460
- int i ;
508
+ struct probe_arg * parg ;
509
+ int i , j ;
461
510
int pos = 0 ;
462
-
463
511
const char * fmt , * arg ;
464
512
465
513
if (!is_return ) {
@@ -470,33 +518,49 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len,
470
518
arg = "REC->" FIELD_STRING_FUNC ", REC->" FIELD_STRING_RETIP ;
471
519
}
472
520
473
- /* When len=0, we just calculate the needed length */
474
- #define LEN_OR_ZERO (len ? len - pos : 0)
475
-
476
521
pos += snprintf (buf + pos , LEN_OR_ZERO , "\"%s" , fmt );
477
522
478
523
for (i = 0 ; i < tp -> nr_args ; i ++ ) {
479
- pos += snprintf (buf + pos , LEN_OR_ZERO , " %s=%s" ,
480
- tp -> args [i ].name , tp -> args [i ].type -> fmt );
524
+ parg = tp -> args + i ;
525
+ pos += snprintf (buf + pos , LEN_OR_ZERO , " %s=" , parg -> name );
526
+ if (parg -> count ) {
527
+ pos += snprintf (buf + pos , LEN_OR_ZERO , "{%s" ,
528
+ parg -> type -> fmt );
529
+ for (j = 1 ; j < parg -> count ; j ++ )
530
+ pos += snprintf (buf + pos , LEN_OR_ZERO , ",%s" ,
531
+ parg -> type -> fmt );
532
+ pos += snprintf (buf + pos , LEN_OR_ZERO , "}" );
533
+ } else
534
+ pos += snprintf (buf + pos , LEN_OR_ZERO , "%s" ,
535
+ parg -> type -> fmt );
481
536
}
482
537
483
538
pos += snprintf (buf + pos , LEN_OR_ZERO , "\", %s" , arg );
484
539
485
540
for (i = 0 ; i < tp -> nr_args ; i ++ ) {
486
- if (strcmp (tp -> args [i ].type -> name , "string" ) == 0 )
541
+ parg = tp -> args + i ;
542
+ if (parg -> count ) {
543
+ if (strcmp (parg -> type -> name , "string" ) == 0 )
544
+ fmt = ", __get_str(%s[%d])" ;
545
+ else
546
+ fmt = ", REC->%s[%d]" ;
547
+ for (j = 0 ; j < parg -> count ; j ++ )
548
+ pos += snprintf (buf + pos , LEN_OR_ZERO ,
549
+ fmt , parg -> name , j );
550
+ } else {
551
+ if (strcmp (parg -> type -> name , "string" ) == 0 )
552
+ fmt = ", __get_str(%s)" ;
553
+ else
554
+ fmt = ", REC->%s" ;
487
555
pos += snprintf (buf + pos , LEN_OR_ZERO ,
488
- ", __get_str(%s)" ,
489
- tp -> args [i ].name );
490
- else
491
- pos += snprintf (buf + pos , LEN_OR_ZERO , ", REC->%s" ,
492
- tp -> args [i ].name );
556
+ fmt , parg -> name );
557
+ }
493
558
}
494
559
495
- #undef LEN_OR_ZERO
496
-
497
560
/* return the length of print_fmt */
498
561
return pos ;
499
562
}
563
+ #undef LEN_OR_ZERO
500
564
501
565
int traceprobe_set_print_fmt (struct trace_probe * tp , bool is_return )
502
566
{
@@ -524,11 +588,15 @@ int traceprobe_define_arg_fields(struct trace_event_call *event_call,
524
588
/* Set argument names as fields */
525
589
for (i = 0 ; i < tp -> nr_args ; i ++ ) {
526
590
struct probe_arg * parg = & tp -> args [i ];
527
-
528
- ret = trace_define_field (event_call , parg -> type -> fmttype ,
529
- parg -> name ,
530
- offset + parg -> offset ,
531
- parg -> type -> size ,
591
+ const char * fmt = parg -> type -> fmttype ;
592
+ int size = parg -> type -> size ;
593
+
594
+ if (parg -> fmt )
595
+ fmt = parg -> fmt ;
596
+ if (parg -> count )
597
+ size *= parg -> count ;
598
+ ret = trace_define_field (event_call , fmt , parg -> name ,
599
+ offset + parg -> offset , size ,
532
600
parg -> type -> is_signed ,
533
601
FILTER_OTHER );
534
602
if (ret )
0 commit comments