hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
kernel/tools/perf/util/probe-event.c
....@@ -1,22 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * probe-event.c : perf-probe definition to probe_events format 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,15 +19,17 @@
3319 #include <limits.h>
3420 #include <elf.h>
3521
36
-#include "util.h"
22
+#include "build-id.h"
3723 #include "event.h"
24
+#include "namespaces.h"
3825 #include "strlist.h"
3926 #include "strfilter.h"
4027 #include "debug.h"
41
-#include "cache.h"
28
+#include "dso.h"
4229 #include "color.h"
30
+#include "map.h"
31
+#include "maps.h"
4332 #include "symbol.h"
44
-#include "thread.h"
4533 #include <api/fs/fs.h>
4634 #include "trace-event.h" /* For __maybe_unused */
4735 #include "probe-event.h"
....@@ -49,13 +37,20 @@
4937 #include "probe-file.h"
5038 #include "session.h"
5139 #include "string2.h"
40
+#include "strbuf.h"
5241
53
-#include "sane_ctype.h"
42
+#include <subcmd/pager.h>
43
+#include <linux/ctype.h>
44
+#include <linux/zalloc.h>
45
+
46
+#ifdef HAVE_DEBUGINFOD_SUPPORT
47
+#include <elfutils/debuginfod.h>
48
+#endif
5449
5550 #define PERFPROBE_GROUP "probe"
5651
5752 bool probe_event_dry_run; /* Dry run flag */
58
-struct probe_conf probe_conf;
53
+struct probe_conf probe_conf = { .magic_num = DEFAULT_PROBE_MAGIC_NUM };
5954
6055 #define semantic_error(msg ...) pr_err("Semantic error :" msg)
6156
....@@ -138,9 +133,10 @@
138133 struct map *map;
139134
140135 /* ref_reloc_sym is just a label. Need a special fix*/
141
- reloc_sym = kernel_get_ref_reloc_sym(NULL);
136
+ reloc_sym = kernel_get_ref_reloc_sym(&map);
142137 if (reloc_sym && strcmp(name, reloc_sym->name) == 0)
143
- *addr = (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr;
138
+ *addr = (!map->reloc || reloc) ? reloc_sym->addr :
139
+ reloc_sym->unrelocated_addr;
144140 else {
145141 sym = machine__find_kernel_symbol_by_name(host_machine, name, &map);
146142 if (!sym)
....@@ -166,7 +162,7 @@
166162 return map__get(pos);
167163 }
168164
169
- for (pos = maps__first(maps); pos; pos = map__next(pos)) {
165
+ maps__for_each_entry(maps, pos) {
170166 /* short_name is "[module]" */
171167 if (strncmp(pos->dso->short_name + 1, module,
172168 pos->dso->short_name_len - 2) == 0 &&
....@@ -231,9 +227,9 @@
231227
232228 static void clear_perf_probe_point(struct perf_probe_point *pp)
233229 {
234
- free(pp->file);
235
- free(pp->function);
236
- free(pp->lazy_line);
230
+ zfree(&pp->file);
231
+ zfree(&pp->function);
232
+ zfree(&pp->lazy_line);
237233 }
238234
239235 static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
....@@ -337,7 +333,7 @@
337333 char module_name[128];
338334
339335 snprintf(module_name, sizeof(module_name), "[%s]", module);
340
- map = map_groups__find_by_name(&host_machine->kmaps, module_name);
336
+ map = maps__find_by_name(&host_machine->kmaps, module_name);
341337 if (map) {
342338 dso = map->dso;
343339 goto found;
....@@ -348,6 +344,8 @@
348344
349345 map = machine__kernel_map(host_machine);
350346 dso = map->dso;
347
+ if (!dso->has_build_id)
348
+ dso__read_running_kernel_build_id(dso, host_machine);
351349
352350 vmlinux_name = symbol_conf.vmlinux_name;
353351 dso->load_errno = 0;
....@@ -386,9 +384,13 @@
386384
387385 /* Find the address of given function */
388386 map__for_each_symbol_by_name(map, pp->function, sym) {
389
- if (uprobes)
387
+ if (uprobes) {
390388 address = sym->start;
391
- else
389
+ if (sym->type == STT_GNU_IFUNC)
390
+ pr_warning("Warning: The probe function (%s) is a GNU indirect function.\n"
391
+ "Consider identifying the final function used at run time and set the probe directly on that.\n",
392
+ pp->function);
393
+ } else
392394 address = map->unmap_ip(map, sym->start) - map->reloc;
393395 break;
394396 }
....@@ -459,6 +461,49 @@
459461 return ret;
460462 }
461463
464
+#ifdef HAVE_DEBUGINFOD_SUPPORT
465
+static struct debuginfo *open_from_debuginfod(struct dso *dso, struct nsinfo *nsi,
466
+ bool silent)
467
+{
468
+ debuginfod_client *c = debuginfod_begin();
469
+ char sbuild_id[SBUILD_ID_SIZE + 1];
470
+ struct debuginfo *ret = NULL;
471
+ struct nscookie nsc;
472
+ char *path;
473
+ int fd;
474
+
475
+ if (!c)
476
+ return NULL;
477
+
478
+ build_id__sprintf(&dso->bid, sbuild_id);
479
+ fd = debuginfod_find_debuginfo(c, (const unsigned char *)sbuild_id,
480
+ 0, &path);
481
+ if (fd >= 0)
482
+ close(fd);
483
+ debuginfod_end(c);
484
+ if (fd < 0) {
485
+ if (!silent)
486
+ pr_debug("Failed to find debuginfo in debuginfod.\n");
487
+ return NULL;
488
+ }
489
+ if (!silent)
490
+ pr_debug("Load debuginfo from debuginfod (%s)\n", path);
491
+
492
+ nsinfo__mountns_enter(nsi, &nsc);
493
+ ret = debuginfo__new((const char *)path);
494
+ nsinfo__mountns_exit(&nsc);
495
+ return ret;
496
+}
497
+#else
498
+static inline
499
+struct debuginfo *open_from_debuginfod(struct dso *dso __maybe_unused,
500
+ struct nsinfo *nsi __maybe_unused,
501
+ bool silent __maybe_unused)
502
+{
503
+ return NULL;
504
+}
505
+#endif
506
+
462507 /* Open new debuginfo of given module */
463508 static struct debuginfo *open_debuginfo(const char *module, struct nsinfo *nsi,
464509 bool silent)
....@@ -478,9 +523,16 @@
478523 strcpy(reason, "(unknown)");
479524 } else
480525 dso__strerror_load(dso, reason, STRERR_BUFSIZE);
481
- if (!silent)
482
- pr_err("Failed to find the path for %s: %s\n",
483
- module ?: "kernel", reason);
526
+ if (dso)
527
+ ret = open_from_debuginfod(dso, nsi, silent);
528
+ if (ret)
529
+ return ret;
530
+ if (!silent) {
531
+ if (module)
532
+ pr_err("Module %s is not loaded, please specify its full path name.\n", module);
533
+ else
534
+ pr_err("Failed to find the path for the kernel: %s\n", reason);
535
+ }
484536 return NULL;
485537 }
486538 path = dso->long_name;
....@@ -701,7 +753,7 @@
701753 return ret;
702754
703755 for (i = 0; i < ntevs && ret >= 0; i++) {
704
- /* point.address is the addres of point.symbol + point.offset */
756
+ /* point.address is the address of point.symbol + point.offset */
705757 tevs[i].point.address -= stext;
706758 tevs[i].point.module = strdup(exec);
707759 if (!tevs[i].point.module) {
....@@ -799,7 +851,8 @@
799851 free(tevs[i].point.symbol);
800852 tevs[i].point.symbol = tmp;
801853 tevs[i].point.offset = tevs[i].point.address -
802
- reloc_sym->unrelocated_addr;
854
+ (map->reloc ? reloc_sym->unrelocated_addr :
855
+ reloc_sym->addr);
803856 }
804857 return skipped;
805858 }
....@@ -954,6 +1007,7 @@
9541007 static int __show_line_range(struct line_range *lr, const char *module,
9551008 bool user)
9561009 {
1010
+ struct build_id bid;
9571011 int l = 1;
9581012 struct int_node *ln;
9591013 struct debuginfo *dinfo;
....@@ -961,6 +1015,7 @@
9611015 int ret;
9621016 char *tmp;
9631017 char sbuf[STRERR_BUFSIZE];
1018
+ char sbuild_id[SBUILD_ID_SIZE] = "";
9641019
9651020 /* Search a line range */
9661021 dinfo = open_debuginfo(module, NULL, false);
....@@ -973,6 +1028,10 @@
9731028 if (!ret)
9741029 ret = debuginfo__find_line_range(dinfo, lr);
9751030 }
1031
+ if (dinfo->build_id) {
1032
+ build_id__init(&bid, dinfo->build_id, BUILD_ID_SIZE);
1033
+ build_id__sprintf(&bid, sbuild_id);
1034
+ }
9761035 debuginfo__delete(dinfo);
9771036 if (ret == 0 || ret == -ENOENT) {
9781037 pr_warning("Specified source line is not found.\n");
....@@ -984,7 +1043,7 @@
9841043
9851044 /* Convert source file path */
9861045 tmp = lr->path;
987
- ret = get_real_path(tmp, lr->comp_dir, &lr->path);
1046
+ ret = find_source_path(tmp, sbuild_id, lr->comp_dir, &lr->path);
9881047
9891048 /* Free old path when new path is assigned */
9901049 if (tmp != lr->path)
....@@ -1195,12 +1254,11 @@
11951254
11961255 void line_range__clear(struct line_range *lr)
11971256 {
1198
- free(lr->function);
1199
- free(lr->file);
1200
- free(lr->path);
1201
- free(lr->comp_dir);
1257
+ zfree(&lr->function);
1258
+ zfree(&lr->file);
1259
+ zfree(&lr->path);
1260
+ zfree(&lr->comp_dir);
12021261 intlist__delete(lr->line_list);
1203
- memset(lr, 0, sizeof(*lr));
12041262 }
12051263
12061264 int line_range__init(struct line_range *lr)
....@@ -1583,6 +1641,17 @@
15831641 str = tmp + 1;
15841642 }
15851643
1644
+ tmp = strchr(str, '@');
1645
+ if (tmp && tmp != str && !strcmp(tmp + 1, "user")) { /* user attr */
1646
+ if (!user_access_is_supported()) {
1647
+ semantic_error("ftrace does not support user access\n");
1648
+ return -EINVAL;
1649
+ }
1650
+ *tmp = '\0';
1651
+ arg->user_access = true;
1652
+ pr_debug("user_access ");
1653
+ }
1654
+
15861655 tmp = strchr(str, ':');
15871656 if (tmp) { /* Type setting */
15881657 *tmp = '\0';
....@@ -1686,6 +1755,16 @@
16861755 ret = parse_perf_probe_point(argv[0], pev);
16871756 if (ret < 0)
16881757 goto out;
1758
+
1759
+ /* Generate event name if needed */
1760
+ if (!pev->event && pev->point.function && pev->point.line
1761
+ && !pev->point.lazy_line && !pev->point.offset) {
1762
+ if (asprintf(&pev->event, "%s_L%d", pev->point.function,
1763
+ pev->point.line) < 0) {
1764
+ ret = -ENOMEM;
1765
+ goto out;
1766
+ }
1767
+ }
16891768
16901769 /* Copy arguments and ensure return probe has no C argument */
16911770 pev->nargs = argc - 1;
....@@ -1830,6 +1909,12 @@
18301909 tp->offset = 0;
18311910 else
18321911 tp->offset = strtoul(fmt2_str, NULL, 10);
1912
+ }
1913
+
1914
+ if (tev->uprobes) {
1915
+ fmt2_str = strchr(p, '(');
1916
+ if (fmt2_str)
1917
+ tp->ref_ctr_offset = strtoul(fmt2_str + 1, NULL, 0);
18331918 }
18341919
18351920 tev->nargs = argc - 2;
....@@ -1979,7 +2064,10 @@
19792064 if (depth < 0)
19802065 return depth;
19812066 }
1982
- err = strbuf_addf(buf, "%+ld(", ref->offset);
2067
+ if (ref->user_access)
2068
+ err = strbuf_addf(buf, "%s%ld(", "+u", ref->offset);
2069
+ else
2070
+ err = strbuf_addf(buf, "%+ld(", ref->offset);
19832071 return (err < 0) ? err : depth;
19842072 }
19852073
....@@ -2025,6 +2113,22 @@
20252113 return err;
20262114 }
20272115
2116
+static int
2117
+synthesize_uprobe_trace_def(struct probe_trace_event *tev, struct strbuf *buf)
2118
+{
2119
+ struct probe_trace_point *tp = &tev->point;
2120
+ int err;
2121
+
2122
+ err = strbuf_addf(buf, "%s:0x%lx", tp->module, tp->address);
2123
+
2124
+ if (err >= 0 && tp->ref_ctr_offset) {
2125
+ if (!uprobe_ref_ctr_is_supported())
2126
+ return -1;
2127
+ err = strbuf_addf(buf, "(0x%lx)", tp->ref_ctr_offset);
2128
+ }
2129
+ return err >= 0 ? 0 : -1;
2130
+}
2131
+
20282132 char *synthesize_probe_trace_command(struct probe_trace_event *tev)
20292133 {
20302134 struct probe_trace_point *tp = &tev->point;
....@@ -2054,15 +2158,17 @@
20542158 }
20552159
20562160 /* Use the tp->address for uprobes */
2057
- if (tev->uprobes)
2058
- err = strbuf_addf(&buf, "%s:0x%lx", tp->module, tp->address);
2059
- else if (!strncmp(tp->symbol, "0x", 2))
2161
+ if (tev->uprobes) {
2162
+ err = synthesize_uprobe_trace_def(tev, &buf);
2163
+ } else if (!strncmp(tp->symbol, "0x", 2)) {
20602164 /* Absolute address. See try_to_find_absolute_address() */
20612165 err = strbuf_addf(&buf, "%s%s0x%lx", tp->module ?: "",
20622166 tp->module ? ":" : "", tp->address);
2063
- else
2167
+ } else {
20642168 err = strbuf_addf(&buf, "%s%s%s+%lu", tp->module ?: "",
20652169 tp->module ? ":" : "", tp->symbol, tp->offset);
2170
+ }
2171
+
20662172 if (err)
20672173 goto error;
20682174
....@@ -2198,15 +2304,15 @@
21982304 struct perf_probe_arg_field *field, *next;
21992305 int i;
22002306
2201
- free(pev->event);
2202
- free(pev->group);
2203
- free(pev->target);
2307
+ zfree(&pev->event);
2308
+ zfree(&pev->group);
2309
+ zfree(&pev->target);
22042310 clear_perf_probe_point(&pev->point);
22052311
22062312 for (i = 0; i < pev->nargs; i++) {
2207
- free(pev->args[i].name);
2208
- free(pev->args[i].var);
2209
- free(pev->args[i].type);
2313
+ zfree(&pev->args[i].name);
2314
+ zfree(&pev->args[i].var);
2315
+ zfree(&pev->args[i].type);
22102316 field = pev->args[i].field;
22112317 while (field) {
22122318 next = field->next;
....@@ -2215,8 +2321,8 @@
22152321 field = next;
22162322 }
22172323 }
2218
- free(pev->args);
2219
- memset(pev, 0, sizeof(*pev));
2324
+ pev->nargs = 0;
2325
+ zfree(&pev->args);
22202326 }
22212327
22222328 #define strdup_or_goto(str, label) \
....@@ -2297,15 +2403,15 @@
22972403 struct probe_trace_arg_ref *ref, *next;
22982404 int i;
22992405
2300
- free(tev->event);
2301
- free(tev->group);
2302
- free(tev->point.symbol);
2303
- free(tev->point.realname);
2304
- free(tev->point.module);
2406
+ zfree(&tev->event);
2407
+ zfree(&tev->group);
2408
+ zfree(&tev->point.symbol);
2409
+ zfree(&tev->point.realname);
2410
+ zfree(&tev->point.module);
23052411 for (i = 0; i < tev->nargs; i++) {
2306
- free(tev->args[i].name);
2307
- free(tev->args[i].value);
2308
- free(tev->args[i].type);
2412
+ zfree(&tev->args[i].name);
2413
+ zfree(&tev->args[i].value);
2414
+ zfree(&tev->args[i].type);
23092415 ref = tev->args[i].ref;
23102416 while (ref) {
23112417 next = ref->next;
....@@ -2313,8 +2419,8 @@
23132419 ref = next;
23142420 }
23152421 }
2316
- free(tev->args);
2317
- memset(tev, 0, sizeof(*tev));
2422
+ zfree(&tev->args);
2423
+ tev->nargs = 0;
23182424 }
23192425
23202426 struct kprobe_blacklist_node {
....@@ -2331,8 +2437,8 @@
23312437 while (!list_empty(blacklist)) {
23322438 node = list_first_entry(blacklist,
23332439 struct kprobe_blacklist_node, list);
2334
- list_del(&node->list);
2335
- free(node->symbol);
2440
+ list_del_init(&node->list);
2441
+ zfree(&node->symbol);
23362442 free(node);
23372443 }
23382444 }
....@@ -2646,6 +2752,13 @@
26462752 {
26472753 int i;
26482754 char *buf = synthesize_probe_trace_command(tev);
2755
+ struct probe_trace_point *tp = &tev->point;
2756
+
2757
+ if (tp->ref_ctr_offset && !uprobe_ref_ctr_is_supported()) {
2758
+ pr_warning("A semaphore is associated with %s:%s and "
2759
+ "seems your kernel doesn't support it.\n",
2760
+ tev->group, tev->event);
2761
+ }
26492762
26502763 /* Old uprobe event doesn't support memory dereference */
26512764 if (!tev->uprobes || tev->nargs == 0 || !buf)
....@@ -2706,8 +2819,13 @@
27062819 if (tev->event == NULL || tev->group == NULL)
27072820 return -ENOMEM;
27082821
2709
- /* Add added event name to namelist */
2710
- strlist__add(namelist, event);
2822
+ /*
2823
+ * Add new event name to namelist if multiprobe event is NOT
2824
+ * supported, since we have to use new event name for following
2825
+ * probes in that case.
2826
+ */
2827
+ if (!multiprobe_event_is_supported())
2828
+ strlist__add(namelist, event);
27112829 return 0;
27122830 }
27132831
....@@ -2922,6 +3040,16 @@
29223040 if (sym->type != STT_FUNC)
29233041 continue;
29243042
3043
+ /* There can be duplicated symbols in the map */
3044
+ for (i = 0; i < j; i++)
3045
+ if (sym->start == syms[i]->start) {
3046
+ pr_debug("Found duplicated symbol %s @ %" PRIx64 "\n",
3047
+ sym->name, sym->start);
3048
+ break;
3049
+ }
3050
+ if (i != j)
3051
+ continue;
3052
+
29253053 tev = (*tevs) + ret;
29263054 tp = &tev->point;
29273055 if (ret == num_matched_functions) {
....@@ -3047,7 +3175,7 @@
30473175 /*
30483176 * Give it a '0x' leading symbol name.
30493177 * In __add_probe_trace_events, a NULL symbol is interpreted as
3050
- * invalud.
3178
+ * invalid.
30513179 */
30523180 if (asprintf(&tp->symbol, "0x%lx", tp->address) < 0)
30533181 goto errout;
....@@ -3513,7 +3641,8 @@
35133641 /* Show all (filtered) symbols */
35143642 setup_pager();
35153643
3516
- for (nd = rb_first(&map->dso->symbol_names); nd; nd = rb_next(nd)) {
3644
+ for (nd = rb_first_cached(&map->dso->symbol_names); nd;
3645
+ nd = rb_next(nd)) {
35173646 struct symbol_name_rb_node *pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
35183647
35193648 if (strfilter__compare(_filter, pos->sym.name))