hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/tools/perf/util/probe-finder.c
....@@ -1,22 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * probe-finder.c : C expression to kprobe event converter
34 *
45 * Written by Masami Hiramatsu <mhiramat@redhat.com>
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU General Public License
17
- * along with this program; if not, write to the Free Software
18
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
- *
206 */
217
228 #include <inttypes.h>
....@@ -33,16 +19,21 @@
3319 #include <dwarf-regs.h>
3420
3521 #include <linux/bitops.h>
22
+#include <linux/zalloc.h>
3623 #include "event.h"
3724 #include "dso.h"
3825 #include "debug.h"
3926 #include "intlist.h"
40
-#include "util.h"
27
+#include "strbuf.h"
4128 #include "strlist.h"
4229 #include "symbol.h"
4330 #include "probe-finder.h"
4431 #include "probe-file.h"
4532 #include "string2.h"
33
+
34
+#ifdef HAVE_DEBUGINFOD_SUPPORT
35
+#include <elfutils/debuginfod.h>
36
+#endif
4637
4738 /* Kprobe tracer basic type is up to u64 */
4839 #define MAX_BASIC_TYPE_BITS 64
....@@ -64,6 +55,7 @@
6455 static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
6556 const char *path)
6657 {
58
+ GElf_Addr dummy;
6759 int fd;
6860
6961 fd = open(path, O_RDONLY);
....@@ -82,6 +74,8 @@
8274 dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
8375 if (!dbg->dbg)
8476 goto error;
77
+
78
+ dwfl_module_build_id(dbg->mod, &dbg->build_id, &dummy);
8579
8680 dwfl_report_end(dbg->dwfl, NULL, NULL);
8781
....@@ -191,6 +185,20 @@
191185 if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
192186 goto static_var;
193187
188
+ /* Constant value */
189
+ if (dwarf_attr(vr_die, DW_AT_const_value, &attr) &&
190
+ immediate_value_is_supported()) {
191
+ Dwarf_Sword snum;
192
+
193
+ if (!tvar)
194
+ return 0;
195
+
196
+ dwarf_formsdata(&attr, &snum);
197
+ ret = asprintf(&tvar->value, "\\%ld", (long)snum);
198
+
199
+ return ret < 0 ? -ENOMEM : 0;
200
+ }
201
+
194202 /* TODO: handle more than 1 exprs */
195203 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
196204 return -EINVAL; /* Broken DIE ? */
....@@ -295,7 +303,7 @@
295303
296304 static int convert_variable_type(Dwarf_Die *vr_die,
297305 struct probe_trace_arg *tvar,
298
- const char *cast)
306
+ const char *cast, bool user_access)
299307 {
300308 struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
301309 Dwarf_Die type;
....@@ -306,7 +314,8 @@
306314 char prefix;
307315
308316 /* TODO: check all types */
309
- if (cast && strcmp(cast, "string") != 0 && strcmp(cast, "x") != 0 &&
317
+ if (cast && strcmp(cast, "string") != 0 && strcmp(cast, "ustring") &&
318
+ strcmp(cast, "x") != 0 &&
310319 strcmp(cast, "s") != 0 && strcmp(cast, "u") != 0) {
311320 /* Non string type is OK */
312321 /* and respect signedness/hexadecimal cast */
....@@ -335,7 +344,8 @@
335344 pr_debug("%s type is %s.\n",
336345 dwarf_diename(vr_die), dwarf_diename(&type));
337346
338
- if (cast && strcmp(cast, "string") == 0) { /* String type */
347
+ if (cast && (!strcmp(cast, "string") || !strcmp(cast, "ustring"))) {
348
+ /* String type */
339349 ret = dwarf_tag(&type);
340350 if (ret != DW_TAG_pointer_type &&
341351 ret != DW_TAG_array_type) {
....@@ -358,6 +368,7 @@
358368 pr_warning("Out of memory error\n");
359369 return -ENOMEM;
360370 }
371
+ (*ref_ptr)->user_access = user_access;
361372 }
362373 if (!die_compare_name(&type, "char") &&
363374 !die_compare_name(&type, "unsigned char")) {
....@@ -412,7 +423,7 @@
412423 static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
413424 struct perf_probe_arg_field *field,
414425 struct probe_trace_arg_ref **ref_ptr,
415
- Dwarf_Die *die_mem)
426
+ Dwarf_Die *die_mem, bool user_access)
416427 {
417428 struct probe_trace_arg_ref *ref = *ref_ptr;
418429 Dwarf_Die type;
....@@ -449,6 +460,7 @@
449460 *ref_ptr = ref;
450461 }
451462 ref->offset += dwarf_bytesize(&type) * field->index;
463
+ ref->user_access = user_access;
452464 goto next;
453465 } else if (tag == DW_TAG_pointer_type) {
454466 /* Check the pointer and dereference */
....@@ -520,19 +532,28 @@
520532 }
521533 }
522534 ref->offset += (long)offs;
535
+ ref->user_access = user_access;
523536
524537 /* If this member is unnamed, we need to reuse this field */
525538 if (!dwarf_diename(die_mem))
526539 return convert_variable_fields(die_mem, varname, field,
527
- &ref, die_mem);
540
+ &ref, die_mem, user_access);
528541
529542 next:
530543 /* Converting next field */
531544 if (field->next)
532545 return convert_variable_fields(die_mem, field->name,
533
- field->next, &ref, die_mem);
546
+ field->next, &ref, die_mem, user_access);
534547 else
535548 return 0;
549
+}
550
+
551
+static void print_var_not_found(const char *varname)
552
+{
553
+ pr_err("Failed to find the location of the '%s' variable at this address.\n"
554
+ " Perhaps it has been optimized out.\n"
555
+ " Use -V with the --range option to show '%s' location range.\n",
556
+ varname, varname);
536557 }
537558
538559 /* Show a variables in kprobe event format */
....@@ -546,21 +567,22 @@
546567
547568 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
548569 &pf->sp_die, pf->machine, pf->tvar);
570
+ if (ret == -ENOENT && pf->skip_empty_arg)
571
+ /* This can be found in other place. skip it */
572
+ return 0;
549573 if (ret == -ENOENT || ret == -EINVAL) {
550
- pr_err("Failed to find the location of the '%s' variable at this address.\n"
551
- " Perhaps it has been optimized out.\n"
552
- " Use -V with the --range option to show '%s' location range.\n",
553
- pf->pvar->var, pf->pvar->var);
574
+ print_var_not_found(pf->pvar->var);
554575 } else if (ret == -ENOTSUP)
555576 pr_err("Sorry, we don't support this variable location yet.\n");
556577 else if (ret == 0 && pf->pvar->field) {
557578 ret = convert_variable_fields(vr_die, pf->pvar->var,
558579 pf->pvar->field, &pf->tvar->ref,
559
- &die_mem);
580
+ &die_mem, pf->pvar->user_access);
560581 vr_die = &die_mem;
561582 }
562583 if (ret == 0)
563
- ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
584
+ ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type,
585
+ pf->pvar->user_access);
564586 /* *expr will be cached in libdw. Don't free it. */
565587 return ret;
566588 }
....@@ -596,6 +618,8 @@
596618 /* Search again in global variables */
597619 if (!die_find_variable_at(&pf->cu_die, pf->pvar->var,
598620 0, &vr_die)) {
621
+ if (pf->skip_empty_arg)
622
+ return 0;
599623 pr_warning("Failed to find '%s' in this function.\n",
600624 pf->pvar->var);
601625 ret = -ENOENT;
....@@ -790,6 +814,39 @@
790814 return fsp.found ? die_mem : NULL;
791815 }
792816
817
+static int verify_representive_line(struct probe_finder *pf, const char *fname,
818
+ int lineno, Dwarf_Addr addr)
819
+{
820
+ const char *__fname, *__func = NULL;
821
+ Dwarf_Die die_mem;
822
+ int __lineno;
823
+
824
+ /* Verify line number and address by reverse search */
825
+ if (cu_find_lineinfo(&pf->cu_die, addr, &__fname, &__lineno) < 0)
826
+ return 0;
827
+
828
+ pr_debug2("Reversed line: %s:%d\n", __fname, __lineno);
829
+ if (strcmp(fname, __fname) || lineno == __lineno)
830
+ return 0;
831
+
832
+ pr_warning("This line is sharing the address with other lines.\n");
833
+
834
+ if (pf->pev->point.function) {
835
+ /* Find best match function name and lines */
836
+ pf->addr = addr;
837
+ if (find_best_scope(pf, &die_mem)
838
+ && die_match_name(&die_mem, pf->pev->point.function)
839
+ && dwarf_decl_line(&die_mem, &lineno) == 0) {
840
+ __func = dwarf_diename(&die_mem);
841
+ __lineno -= lineno;
842
+ }
843
+ }
844
+ pr_warning("Please try to probe at %s:%d instead.\n",
845
+ __func ? : __fname, __lineno);
846
+
847
+ return -ENOENT;
848
+}
849
+
793850 static int probe_point_line_walker(const char *fname, int lineno,
794851 Dwarf_Addr addr, void *data)
795852 {
....@@ -799,6 +856,9 @@
799856
800857 if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0)
801858 return 0;
859
+
860
+ if (verify_representive_line(pf, fname, lineno, addr))
861
+ return -ENOENT;
802862
803863 pf->addr = addr;
804864 sc_die = find_best_scope(pf, &die_mem);
....@@ -892,6 +952,8 @@
892952 /* Find probe points from lazy pattern */
893953 static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
894954 {
955
+ struct build_id bid;
956
+ char sbuild_id[SBUILD_ID_SIZE] = "";
895957 int ret = 0;
896958 char *fpath;
897959
....@@ -899,7 +961,11 @@
899961 const char *comp_dir;
900962
901963 comp_dir = cu_get_comp_dir(&pf->cu_die);
902
- ret = get_real_path(pf->fname, comp_dir, &fpath);
964
+ if (pf->dbg->build_id) {
965
+ build_id__init(&bid, pf->dbg->build_id, BUILD_ID_SIZE);
966
+ build_id__sprintf(&bid, sbuild_id);
967
+ }
968
+ ret = find_source_path(pf->fname, sbuild_id, comp_dir, &fpath);
903969 if (ret < 0) {
904970 pr_warning("Failed to find source file path.\n");
905971 return ret;
....@@ -1262,6 +1328,17 @@
12621328 return n;
12631329 }
12641330
1331
+static bool trace_event_finder_overlap(struct trace_event_finder *tf)
1332
+{
1333
+ int i;
1334
+
1335
+ for (i = 0; i < tf->ntevs; i++) {
1336
+ if (tf->pf.addr == tf->tevs[i].point.address)
1337
+ return true;
1338
+ }
1339
+ return false;
1340
+}
1341
+
12651342 /* Add a found probe point into trace event list */
12661343 static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
12671344 {
....@@ -1271,6 +1348,14 @@
12711348 struct probe_trace_event *tev;
12721349 struct perf_probe_arg *args = NULL;
12731350 int ret, i;
1351
+
1352
+ /*
1353
+ * For some reason (e.g. different column assigned to same address)
1354
+ * This callback can be called with the address which already passed.
1355
+ * Ignore it first.
1356
+ */
1357
+ if (trace_event_finder_overlap(tf))
1358
+ return 0;
12741359
12751360 /* Check number of tevs */
12761361 if (tf->ntevs == tf->max_tevs) {
....@@ -1332,13 +1417,54 @@
13321417 return ret;
13331418 }
13341419
1420
+static int fill_empty_trace_arg(struct perf_probe_event *pev,
1421
+ struct probe_trace_event *tevs, int ntevs)
1422
+{
1423
+ char **valp;
1424
+ char *type;
1425
+ int i, j, ret;
1426
+
1427
+ if (!ntevs)
1428
+ return -ENOENT;
1429
+
1430
+ for (i = 0; i < pev->nargs; i++) {
1431
+ type = NULL;
1432
+ for (j = 0; j < ntevs; j++) {
1433
+ if (tevs[j].args[i].value) {
1434
+ type = tevs[j].args[i].type;
1435
+ break;
1436
+ }
1437
+ }
1438
+ if (j == ntevs) {
1439
+ print_var_not_found(pev->args[i].var);
1440
+ return -ENOENT;
1441
+ }
1442
+ for (j = 0; j < ntevs; j++) {
1443
+ valp = &tevs[j].args[i].value;
1444
+ if (*valp)
1445
+ continue;
1446
+
1447
+ ret = asprintf(valp, "\\%lx", probe_conf.magic_num);
1448
+ if (ret < 0)
1449
+ return -ENOMEM;
1450
+ /* Note that type can be NULL */
1451
+ if (type) {
1452
+ tevs[j].args[i].type = strdup(type);
1453
+ if (!tevs[j].args[i].type)
1454
+ return -ENOMEM;
1455
+ }
1456
+ }
1457
+ }
1458
+ return 0;
1459
+}
1460
+
13351461 /* Find probe_trace_events specified by perf_probe_event from debuginfo */
13361462 int debuginfo__find_trace_events(struct debuginfo *dbg,
13371463 struct perf_probe_event *pev,
13381464 struct probe_trace_event **tevs)
13391465 {
13401466 struct trace_event_finder tf = {
1341
- .pf = {.pev = pev, .callback = add_probe_trace_event},
1467
+ .pf = {.pev = pev, .dbg = dbg, .callback = add_probe_trace_event},
13421468 .max_tevs = probe_conf.max_probes, .mod = dbg->mod};
13431469 int ret, i;
13441470
....@@ -1350,7 +1476,13 @@
13501476 tf.tevs = *tevs;
13511477 tf.ntevs = 0;
13521478
1479
+ if (pev->nargs != 0 && immediate_value_is_supported())
1480
+ tf.pf.skip_empty_arg = true;
1481
+
13531482 ret = debuginfo__find_probes(dbg, &tf.pf);
1483
+ if (ret >= 0 && tf.pf.skip_empty_arg)
1484
+ ret = fill_empty_trace_arg(pev, tf.tevs, tf.ntevs);
1485
+
13541486 if (ret < 0 || tf.ntevs == 0) {
13551487 for (i = 0; i < tf.ntevs; i++)
13561488 clear_probe_trace_event(&tf.tevs[i]);
....@@ -1502,7 +1634,7 @@
15021634 struct variable_list **vls)
15031635 {
15041636 struct available_var_finder af = {
1505
- .pf = {.pev = pev, .callback = add_available_vars},
1637
+ .pf = {.pev = pev, .dbg = dbg, .callback = add_available_vars},
15061638 .mod = dbg->mod,
15071639 .max_vls = probe_conf.max_probes};
15081640 int ret;
....@@ -1693,10 +1825,17 @@
16931825 void *data)
16941826 {
16951827 struct line_finder *lf = data;
1828
+ const char *__fname;
1829
+ int __lineno;
16961830 int err;
16971831
16981832 if ((strtailcmp(fname, lf->fname) != 0) ||
16991833 (lf->lno_s > lineno || lf->lno_e < lineno))
1834
+ return 0;
1835
+
1836
+ /* Make sure this line can be reversable */
1837
+ if (cu_find_lineinfo(&lf->cu_die, addr, &__fname, &__lineno) > 0
1838
+ && (lineno != __lineno || strcmp(fname, __fname)))
17001839 return 0;
17011840
17021841 err = line_range_add_line(fname, lineno, lf->lr);
....@@ -1749,8 +1888,7 @@
17491888 if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
17501889 return DWARF_CB_OK;
17511890
1752
- if (die_is_func_def(sp_die) &&
1753
- die_match_name(sp_die, lr->function)) {
1891
+ if (die_match_name(sp_die, lr->function) && die_is_func_def(sp_die)) {
17541892 lf->fname = dwarf_decl_file(sp_die);
17551893 dwarf_decl_line(sp_die, &lr->offset);
17561894 pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
....@@ -1850,17 +1988,57 @@
18501988 return (ret < 0) ? ret : lf.found;
18511989 }
18521990
1991
+#ifdef HAVE_DEBUGINFOD_SUPPORT
1992
+/* debuginfod doesn't require the comp_dir but buildid is required */
1993
+static int get_source_from_debuginfod(const char *raw_path,
1994
+ const char *sbuild_id, char **new_path)
1995
+{
1996
+ debuginfod_client *c = debuginfod_begin();
1997
+ const char *p = raw_path;
1998
+ int fd;
1999
+
2000
+ if (!c)
2001
+ return -ENOMEM;
2002
+
2003
+ fd = debuginfod_find_source(c, (const unsigned char *)sbuild_id,
2004
+ 0, p, new_path);
2005
+ pr_debug("Search %s from debuginfod -> %d\n", p, fd);
2006
+ if (fd >= 0)
2007
+ close(fd);
2008
+ debuginfod_end(c);
2009
+ if (fd < 0) {
2010
+ pr_debug("Failed to find %s in debuginfod (%s)\n",
2011
+ raw_path, sbuild_id);
2012
+ return -ENOENT;
2013
+ }
2014
+ pr_debug("Got a source %s\n", *new_path);
2015
+
2016
+ return 0;
2017
+}
2018
+#else
2019
+static inline int get_source_from_debuginfod(const char *raw_path __maybe_unused,
2020
+ const char *sbuild_id __maybe_unused,
2021
+ char **new_path __maybe_unused)
2022
+{
2023
+ return -ENOTSUP;
2024
+}
2025
+#endif
18532026 /*
18542027 * Find a src file from a DWARF tag path. Prepend optional source path prefix
18552028 * and chop off leading directories that do not exist. Result is passed back as
18562029 * a newly allocated path on success.
18572030 * Return 0 if file was found and readable, -errno otherwise.
18582031 */
1859
-int get_real_path(const char *raw_path, const char *comp_dir,
1860
- char **new_path)
2032
+int find_source_path(const char *raw_path, const char *sbuild_id,
2033
+ const char *comp_dir, char **new_path)
18612034 {
18622035 const char *prefix = symbol_conf.source_prefix;
18632036
2037
+ if (sbuild_id && !prefix) {
2038
+ if (!get_source_from_debuginfod(raw_path, sbuild_id, new_path))
2039
+ return 0;
2040
+ }
2041
+
18642042 if (!prefix) {
18652043 if (raw_path[0] != '/' && comp_dir)
18662044 /* If not an absolute path, try to use comp_dir */