Skip to content

Commit 080e47b

Browse files
mhiramatacmel
authored andcommitted
perf probe: Introduce quotation marks support
In non-C languages, it is possible to have ':' in the function names. It is possible to escape it with backslashes, but if there are too many backslashes, it is annoying. This introduce quotation marks (`"` or `'`) support. For example, without quotes, we have to pass it as below $ perf probe -x cro3 -L "cro3\:\:cmd\:\:servo\:\:run_show" <run_show@/work/cro3/src/cmd/servo.rs:0> 0 fn run_show(args: &ArgsShow) -> Result<()> { 1 let list = ServoList::discover()?; 2 let s = list.find_by_serial(&args.servo)?; 3 if args.json { 4 println!("{s}"); With quotes, we can more naturally write the function name as below; $ perf probe -x cro3 -L \"cro3::cmd::servo::run_show\" <run_show@/work/cro3/src/cmd/servo.rs:0> 0 fn run_show(args: &ArgsShow) -> Result<()> { 1 let list = ServoList::discover()?; 2 let s = list.find_by_serial(&args.servo)?; 3 if args.json { 4 println!("{s}"); Signed-off-by: Masami Hiramatsu <[email protected]> Cc: Alexander Lobakin <[email protected]> Cc: Dima Kogan <[email protected]> Cc: Ian Rogers <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Przemek Kitszel <[email protected]> Link: https://lore.kernel.org/r/173099116941.2431889.11609129616090100386.stgit@mhiramat.roam.corp.google.com Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 313026f commit 080e47b

File tree

1 file changed

+41
-34
lines changed

1 file changed

+41
-34
lines changed

tools/perf/util/probe-event.c

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,7 @@ static int __show_line_range(struct line_range *lr, const char *module,
10791079

10801080
ret = debuginfo__find_line_range(dinfo, lr);
10811081
if (!ret) { /* Not found, retry with an alternative */
1082+
pr_debug2("Failed to find line range in debuginfo. Fallback to alternative\n");
10821083
ret = get_alternative_line_range(dinfo, lr, module, user);
10831084
if (!ret)
10841085
ret = debuginfo__find_line_range(dinfo, lr);
@@ -1362,30 +1363,37 @@ static bool is_c_func_name(const char *name)
13621363
* FNC[@SRC][:SLN[+NUM|-ELN]]
13631364
*
13641365
* FNC@SRC accepts `FNC@*` which forcibly specify FNC as function name.
1366+
* SRC and FUNC can be quoted by double/single quotes.
13651367
*/
13661368
int parse_line_range_desc(const char *arg, struct line_range *lr)
13671369
{
1368-
char *range, *file, *name = strdup(arg);
1370+
char *buf = strdup(arg);
1371+
char *p;
13691372
int err;
13701373

1371-
if (!name)
1374+
if (!buf)
13721375
return -ENOMEM;
13731376

13741377
lr->start = 0;
13751378
lr->end = INT_MAX;
13761379

1377-
range = strpbrk_esc(name, ":");
1378-
if (range) {
1379-
*range++ = '\0';
1380+
p = strpbrk_esq(buf, ":");
1381+
if (p) {
1382+
if (p == buf) {
1383+
semantic_error("No file/function name in '%s'.\n", p);
1384+
err = -EINVAL;
1385+
goto err;
1386+
}
1387+
*(p++) = '\0';
13801388

1381-
err = parse_line_num(&range, &lr->start, "start line");
1389+
err = parse_line_num(&p, &lr->start, "start line");
13821390
if (err)
13831391
goto err;
13841392

1385-
if (*range == '+' || *range == '-') {
1386-
const char c = *range++;
1393+
if (*p == '+' || *p == '-') {
1394+
const char c = *(p++);
13871395

1388-
err = parse_line_num(&range, &lr->end, "end line");
1396+
err = parse_line_num(&p, &lr->end, "end line");
13891397
if (err)
13901398
goto err;
13911399

@@ -1409,62 +1417,61 @@ int parse_line_range_desc(const char *arg, struct line_range *lr)
14091417
" than end line.\n");
14101418
goto err;
14111419
}
1412-
if (*range != '\0') {
1413-
semantic_error("Tailing with invalid str '%s'.\n", range);
1420+
if (*p != '\0') {
1421+
semantic_error("Tailing with invalid str '%s'.\n", p);
14141422
goto err;
14151423
}
14161424
}
14171425

1418-
file = strpbrk_esc(name, "@");
1419-
if (file) {
1420-
*file++ = '\0';
1421-
if (strcmp(file, "*")) {
1422-
lr->file = strdup_esc(file);
1426+
p = strpbrk_esq(buf, "@");
1427+
if (p) {
1428+
*p++ = '\0';
1429+
if (strcmp(p, "*")) {
1430+
lr->file = strdup_esq(p);
14231431
if (lr->file == NULL) {
14241432
err = -ENOMEM;
14251433
goto err;
14261434
}
14271435
}
1428-
if (*name != '\0')
1429-
lr->function = name;
1436+
if (*buf != '\0')
1437+
lr->function = strdup_esq(buf);
14301438
if (!lr->function && !lr->file) {
14311439
semantic_error("Only '@*' is not allowed.\n");
14321440
err = -EINVAL;
14331441
goto err;
14341442
}
1435-
} else if (strpbrk_esc(name, "/."))
1436-
lr->file = name;
1437-
else if (is_c_func_name(name))/* We reuse it for checking funcname */
1438-
lr->function = name;
1443+
} else if (strpbrk_esq(buf, "/."))
1444+
lr->file = strdup_esq(buf);
1445+
else if (is_c_func_name(buf))/* We reuse it for checking funcname */
1446+
lr->function = strdup_esq(buf);
14391447
else { /* Invalid name */
1440-
semantic_error("'%s' is not a valid function name.\n", name);
1448+
semantic_error("'%s' is not a valid function name.\n", buf);
14411449
err = -EINVAL;
14421450
goto err;
14431451
}
14441452

1445-
return 0;
14461453
err:
1447-
free(name);
1454+
free(buf);
14481455
return err;
14491456
}
14501457

14511458
static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev)
14521459
{
14531460
char *ptr;
14541461

1455-
ptr = strpbrk_esc(*arg, ":");
1462+
ptr = strpbrk_esq(*arg, ":");
14561463
if (ptr) {
14571464
*ptr = '\0';
14581465
if (!pev->sdt && !is_c_func_name(*arg))
14591466
goto ng_name;
1460-
pev->group = strdup_esc(*arg);
1467+
pev->group = strdup_esq(*arg);
14611468
if (!pev->group)
14621469
return -ENOMEM;
14631470
*arg = ptr + 1;
14641471
} else
14651472
pev->group = NULL;
14661473

1467-
pev->event = strdup_esc(*arg);
1474+
pev->event = strdup_esq(*arg);
14681475
if (pev->event == NULL)
14691476
return -ENOMEM;
14701477

@@ -1503,7 +1510,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
15031510
arg++;
15041511
}
15051512

1506-
ptr = strpbrk_esc(arg, ";=@+%");
1513+
ptr = strpbrk_esq(arg, ";=@+%");
15071514
if (pev->sdt) {
15081515
if (ptr) {
15091516
if (*ptr != '@') {
@@ -1517,7 +1524,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
15171524
pev->target = build_id_cache__origname(tmp);
15181525
free(tmp);
15191526
} else
1520-
pev->target = strdup_esc(ptr + 1);
1527+
pev->target = strdup_esq(ptr + 1);
15211528
if (!pev->target)
15221529
return -ENOMEM;
15231530
*ptr = '\0';
@@ -1558,7 +1565,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
15581565
file_spec = true;
15591566
}
15601567

1561-
ptr = strpbrk_esc(arg, ";:+@%");
1568+
ptr = strpbrk_esq(arg, ";:+@%");
15621569
if (ptr) {
15631570
nc = *ptr;
15641571
*ptr++ = '\0';
@@ -1567,7 +1574,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
15671574
if (arg[0] == '\0')
15681575
tmp = NULL;
15691576
else {
1570-
tmp = strdup_esc(arg);
1577+
tmp = strdup_esq(arg);
15711578
if (tmp == NULL)
15721579
return -ENOMEM;
15731580
}
@@ -1605,7 +1612,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
16051612
return -ENOMEM;
16061613
break;
16071614
}
1608-
ptr = strpbrk_esc(arg, ";:+@%");
1615+
ptr = strpbrk_esq(arg, ";:+@%");
16091616
if (ptr) {
16101617
nc = *ptr;
16111618
*ptr++ = '\0';
@@ -1634,7 +1641,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
16341641
}
16351642
if (!strcmp(arg, "*"))
16361643
break;
1637-
pp->file = strdup_esc(arg);
1644+
pp->file = strdup_esq(arg);
16381645
if (pp->file == NULL)
16391646
return -ENOMEM;
16401647
break;

0 commit comments

Comments
 (0)