1e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* 2e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * probe-event.c : perf-probe definition to probe_events format converter 3e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 4e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Written by Masami Hiramatsu <mhiramat@redhat.com> 5e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 6e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * This program is free software; you can redistribute it and/or modify 7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * it under the terms of the GNU General Public License as published by 8e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * the Free Software Foundation; either version 2 of the License, or 9e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * (at your option) any later version. 10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * This program is distributed in the hope that it will be useful, 12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * but WITHOUT ANY WARRANTY; without even the implied warranty of 13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * GNU General Public License for more details. 15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * You should have received a copy of the GNU General Public License 17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * along with this program; if not, write to the Free Software 18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define _GNU_SOURCE 23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <sys/utsname.h> 24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <sys/types.h> 25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <sys/stat.h> 26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <fcntl.h> 27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <errno.h> 28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <stdio.h> 29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <unistd.h> 30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <stdlib.h> 31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <string.h> 32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <stdarg.h> 33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <limits.h> 34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <elf.h> 35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#undef _GNU_SOURCE 37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "util.h" 38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "event.h" 39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "string.h" 40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "strlist.h" 41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "debug.h" 42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "cache.h" 43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "color.h" 44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "symbol.h" 45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "thread.h" 46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "debugfs.h" 47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "trace-event.h" /* For __unused */ 48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "probe-event.h" 49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "probe-finder.h" 50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define MAX_CMDLEN 256 52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define MAX_PROBE_ARGS 128 53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define PERFPROBE_GROUP "probe" 54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengbool probe_event_dry_run; /* Dry run flag */ 56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define semantic_error(msg ...) pr_err("Semantic error :" msg) 58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* If there is no space to write, returns -E2BIG. */ 60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int e_snprintf(char *str, size_t size, const char *format, ...) 61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng __attribute__((format(printf, 3, 4))); 62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int e_snprintf(char *str, size_t size, const char *format, ...) 64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret; 66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng va_list ap; 67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng va_start(ap, format); 68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = vsnprintf(str, size, format, ap); 69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng va_end(ap); 70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret >= (int)size) 71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -E2BIG; 72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic char *synthesize_perf_probe_point(struct perf_probe_point *pp); 76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct machine machine; 77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Initialize symbol maps and path of vmlinux/modules */ 79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int init_vmlinux(void) 80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret; 82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symbol_conf.sort_by_name = true; 84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (symbol_conf.vmlinux_name == NULL) 85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symbol_conf.try_vmlinux_path = true; 86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name); 88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = symbol__init(); 89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) { 90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Failed to init symbol map.\n"); 91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 93e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 94e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = machine__init(&machine, "", HOST_KERNEL_ID); 95e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 96e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 97e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 98e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (machine__create_kernel_maps(&machine) < 0) { 99e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("machine__create_kernel_maps() failed.\n"); 100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout: 103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Failed to init vmlinux path.\n"); 105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct symbol *__find_kernel_function_by_name(const char *name, 109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map **mapp) 110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return machine__find_kernel_function_by_name(&machine, name, mapp, 112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng NULL); 113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct map *kernel_get_module_map(const char *module) 116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *nd; 118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map_groups *grp = &machine.kmaps; 119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!module) 121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng module = "kernel"; 122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (nd = rb_first(&grp->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) { 124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *pos = rb_entry(nd, struct map, rb_node); 125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (strncmp(pos->dso->short_name + 1, module, 126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pos->dso->short_name_len - 2) == 0) { 127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return pos; 128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct dso *kernel_get_module_dso(const char *module) 134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct dso *dso; 136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *map; 137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *vmlinux_name; 138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (module) { 140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_for_each_entry(dso, &machine.kernel_dsos, node) { 141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (strncmp(dso->short_name + 1, module, 142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dso->short_name_len - 2) == 0) 143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto found; 144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Failed to find module %s.\n", module); 146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map = machine.vmlinux_maps[MAP__FUNCTION]; 150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dso = map->dso; 151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng vmlinux_name = symbol_conf.vmlinux_name; 153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (vmlinux_name) { 154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (dso__load_vmlinux(dso, map, vmlinux_name, NULL) <= 0) 155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else { 157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (dso__load_vmlinux_path(dso, map, NULL) <= 0) { 158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Failed to load kernel map.\n"); 159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengfound: 163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return dso; 164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengconst char *kernel_get_module_path(const char *module) 167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct dso *dso = kernel_get_module_dso(module); 169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return (dso) ? dso->long_name : NULL; 170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#ifdef DWARF_SUPPORT 173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int open_vmlinux(const char *module) 174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *path = kernel_get_module_path(module); 176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!path) { 177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_err("Failed to find path of %s module.\n", 178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng module ?: "kernel"); 179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOENT; 180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Try to open %s\n", path); 182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return open(path, O_RDONLY); 183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* 186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Convert trace point to probe point with debuginfo 187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Currently only handles kprobes. 188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_probe_point *pp) 191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct symbol *sym; 193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *map; 194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 addr; 195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret = -ENOENT; 196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sym = __find_kernel_function_by_name(tp->symbol, &map); 198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (sym) { 199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng addr = map->unmap_ip(map, sym->start + tp->offset); 200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol, 201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tp->offset, addr); 202e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = find_perf_probe_point((unsigned long)addr, pp); 203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret <= 0) { 205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Failed to find corresponding probes from " 206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "debuginfo. Use kprobe event information.\n"); 207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pp->function = strdup(tp->symbol); 208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->function == NULL) 209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pp->offset = tp->offset; 211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pp->retprobe = tp->retprobe; 213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 215e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 216e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 217e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Try to find perf_probe_event with debuginfo */ 218e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int try_to_find_probe_trace_events(struct perf_probe_event *pev, 219e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct probe_trace_event **tevs, 220e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int max_tevs, const char *module) 221e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 222e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng bool need_dwarf = perf_probe_event_need_dwarf(pev); 223e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int fd, ntevs; 224e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 225e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fd = open_vmlinux(module); 226e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (fd < 0) { 227e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (need_dwarf) { 228e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Failed to open debuginfo file.\n"); 229e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return fd; 230e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 231e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Could not open vmlinux. Try to use symbols.\n"); 232e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 233e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 234e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 235e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Searching trace events corresponding to probe event */ 236e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs); 237e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 238e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ntevs > 0) { /* Succeeded to find trace events */ 239e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("find %d probe_trace_events.\n", ntevs); 240e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ntevs; 241e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 242e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 243e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ntevs == 0) { /* No error but failed to find probe point. */ 244e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Probe point '%s' not found.\n", 245e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng synthesize_perf_probe_point(&pev->point)); 246e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOENT; 247e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 248e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Error path : ntevs < 0 */ 249e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); 250e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ntevs == -EBADF) { 251e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Warning: No dwarf info found in the vmlinux - " 252e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); 253e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!need_dwarf) { 254e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Trying to use symbols.\n"); 255e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 256e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 257e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 258e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ntevs; 259e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 260e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 261e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* 262e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Find a src file from a DWARF tag path. Prepend optional source path prefix 263e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * and chop off leading directories that do not exist. Result is passed back as 264e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * a newly allocated path on success. 265e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Return 0 if file was found and readable, -errno otherwise. 266e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 267e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int get_real_path(const char *raw_path, const char *comp_dir, 268e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char **new_path) 269e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 270e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *prefix = symbol_conf.source_prefix; 271e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 272e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!prefix) { 273e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (raw_path[0] != '/' && comp_dir) 274e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* If not an absolute path, try to use comp_dir */ 275e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng prefix = comp_dir; 276e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else { 277e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (access(raw_path, R_OK) == 0) { 278e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *new_path = strdup(raw_path); 279e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 280e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else 281e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -errno; 282e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 283e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 284e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 285e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2)); 286e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!*new_path) 287e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 288e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 289e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (;;) { 290e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sprintf(*new_path, "%s/%s", prefix, raw_path); 291e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 292e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (access(*new_path, R_OK) == 0) 293e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 294e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 295e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!symbol_conf.source_prefix) 296e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* In case of searching comp_dir, don't retry */ 297e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -errno; 298e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 299e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng switch (errno) { 300e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case ENAMETOOLONG: 301e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case ENOENT: 302e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case EROFS: 303e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case EFAULT: 304e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng raw_path = strchr(++raw_path, '/'); 305e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!raw_path) { 306e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(*new_path); 307e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *new_path = NULL; 308e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOENT; 309e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 310e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 311e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 312e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng default: 313e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(*new_path); 314e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *new_path = NULL; 315e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -errno; 316e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 317e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 318e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 319e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 320e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define LINEBUF_SIZE 256 321e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define NR_ADDITIONAL_LINES 2 322e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 323e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int __show_one_line(FILE *fp, int l, bool skip, bool show_num) 324e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 325e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char buf[LINEBUF_SIZE]; 326e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *color = show_num ? "" : PERF_COLOR_BLUE; 327e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *prefix = NULL; 328e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 329e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng do { 330e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 331e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 332e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (skip) 333e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 334e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!prefix) { 335e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng prefix = show_num ? "%7d " : " "; 336e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng color_fprintf(stdout, color, prefix, l); 337e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 338e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng color_fprintf(stdout, color, "%s", buf); 339e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 340e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } while (strchr(buf, '\n') == NULL); 341e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 342e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 1; 343e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengerror: 344e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ferror(fp)) { 345e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("File read error: %s\n", strerror(errno)); 346e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 347e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 348e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 349e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 350e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 351e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int _show_one_line(FILE *fp, int l, bool skip, bool show_num) 352e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 353e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int rv = __show_one_line(fp, l, skip, show_num); 354e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (rv == 0) { 355e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Source file is shorter than expected.\n"); 356e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rv = -1; 357e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 358e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return rv; 359e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 360e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 361e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define show_one_line_with_num(f,l) _show_one_line(f,l,false,true) 362e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define show_one_line(f,l) _show_one_line(f,l,false,false) 363e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define skip_one_line(f,l) _show_one_line(f,l,true,false) 364e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define show_one_line_or_eof(f,l) __show_one_line(f,l,false,false) 365e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 366e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* 367e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Show line-range always requires debuginfo to find source file and 368e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * line number. 369e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 370e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint show_line_range(struct line_range *lr, const char *module) 371e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 372e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int l = 1; 373e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct line_node *ln; 374e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng FILE *fp; 375e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int fd, ret; 376e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *tmp; 377e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 378e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Search a line range */ 379e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = init_vmlinux(); 380e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 381e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 382e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 383e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fd = open_vmlinux(module); 384e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (fd < 0) { 385e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Failed to open debuginfo file.\n"); 386e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return fd; 387e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 388e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 389e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = find_line_range(fd, lr); 390e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret == 0) { 391e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Specified source line is not found.\n"); 392e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOENT; 393e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else if (ret < 0) { 394e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Debuginfo analysis failed. (%d)\n", ret); 395e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 396e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 397e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 398e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Convert source file path */ 399e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp = lr->path; 400e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = get_real_path(tmp, lr->comp_dir, &lr->path); 401e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(tmp); /* Free old path */ 402e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) { 403e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Failed to find source file. (%d)\n", ret); 404e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 405e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 406e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 407e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng setup_pager(); 408e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 409e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (lr->function) 410e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fprintf(stdout, "<%s@%s:%d>\n", lr->function, lr->path, 411e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng lr->start - lr->offset); 412e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 413e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fprintf(stdout, "<%s:%d>\n", lr->path, lr->start); 414e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 415e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fp = fopen(lr->path, "r"); 416e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (fp == NULL) { 417e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Failed to open %s: %s\n", lr->path, 418e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strerror(errno)); 419e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -errno; 420e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 421e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Skip to starting line number */ 422e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (l < lr->start) { 423e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = skip_one_line(fp, l++); 424e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 425e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto end; 426e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 427e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 428e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_for_each_entry(ln, &lr->line_list, list) { 429e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (; ln->line > l; l++) { 430e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = show_one_line(fp, l - lr->offset); 431e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 432e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto end; 433e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 434e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = show_one_line_with_num(fp, l++ - lr->offset); 435e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 436e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto end; 437e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 438e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 439e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (lr->end == INT_MAX) 440e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng lr->end = l + NR_ADDITIONAL_LINES; 441e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (l <= lr->end) { 442e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = show_one_line_or_eof(fp, l++ - lr->offset); 443e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret <= 0) 444e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 445e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 446e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengend: 447e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fclose(fp); 448e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 449e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 450e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 451e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int show_available_vars_at(int fd, struct perf_probe_event *pev, 452e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int max_vls, struct strfilter *_filter, 453e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng bool externs) 454e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 455e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *buf; 456e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret, i, nvars; 457e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct str_node *node; 458e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct variable_list *vls = NULL, *vl; 459e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *var; 460e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 461e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng buf = synthesize_perf_probe_point(&pev->point); 462e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!buf) 463e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 464e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Searching variables at %s\n", buf); 465e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 466e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = find_available_vars_at(fd, pev, &vls, max_vls, externs); 467e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret <= 0) { 468e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_err("Failed to find variables at %s (%d)\n", buf, ret); 469e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto end; 470e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 471e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Some variables are found */ 472e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fprintf(stdout, "Available variables at %s\n", buf); 473e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < ret; i++) { 474e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng vl = &vls[i]; 475e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 476e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * A probe point might be converted to 477e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * several trace points. 478e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 479e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, 480e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng vl->point.offset); 481e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(vl->point.symbol); 482e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng nvars = 0; 483e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (vl->vars) { 484e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlist__for_each(node, vl->vars) { 485e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng var = strchr(node->s, '\t') + 1; 486e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (strfilter__compare(_filter, var)) { 487e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fprintf(stdout, "\t\t%s\n", node->s); 488e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng nvars++; 489e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 490e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 491e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlist__delete(vl->vars); 492e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 493e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (nvars == 0) 494e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fprintf(stdout, "\t\t(No matched variables)\n"); 495e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 496e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(vls); 497e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengend: 498e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(buf); 499e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 500e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 501e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 502e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Show available variables on given probe point */ 503e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint show_available_vars(struct perf_probe_event *pevs, int npevs, 504e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int max_vls, const char *module, 505e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct strfilter *_filter, bool externs) 506e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 507e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i, fd, ret = 0; 508e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 509e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = init_vmlinux(); 510e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 511e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 512e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 513e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng setup_pager(); 514e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 515e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < npevs && ret >= 0; i++) { 516e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fd = open_vmlinux(module); 517e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (fd < 0) { 518e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Failed to open debug information file.\n"); 519e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = fd; 520e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 521e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 522e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter, 523e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng externs); 524e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 525e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 526e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 527e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 528e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#else /* !DWARF_SUPPORT */ 529e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 530e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 531e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_probe_point *pp) 532e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 533e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct symbol *sym; 534e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 535e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sym = __find_kernel_function_by_name(tp->symbol, NULL); 536e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!sym) { 537e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_err("Failed to find symbol %s in kernel.\n", tp->symbol); 538e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOENT; 539e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 540e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pp->function = strdup(tp->symbol); 541e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->function == NULL) 542e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 543e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pp->offset = tp->offset; 544e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pp->retprobe = tp->retprobe; 545e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 546e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 547e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 548e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 549e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int try_to_find_probe_trace_events(struct perf_probe_event *pev, 550e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct probe_trace_event **tevs __unused, 551e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int max_tevs __unused, const char *mod __unused) 552e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 553e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (perf_probe_event_need_dwarf(pev)) { 554e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Debuginfo-analysis is not supported.\n"); 555e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOSYS; 556e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 557e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 558e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 559e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 560e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint show_line_range(struct line_range *lr __unused, const char *module __unused) 561e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 562e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Debuginfo-analysis is not supported.\n"); 563e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOSYS; 564e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 565e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 566e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint show_available_vars(struct perf_probe_event *pevs __unused, 567e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int npevs __unused, int max_vls __unused, 568e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *module __unused, 569e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct strfilter *filter __unused, 570e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng bool externs __unused) 571e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 572e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Debuginfo-analysis is not supported.\n"); 573e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOSYS; 574e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 575e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#endif 576e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 577e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int parse_line_num(char **ptr, int *val, const char *what) 578e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 579e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *start = *ptr; 580e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 581e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng errno = 0; 582e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *val = strtol(*ptr, ptr, 0); 583e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (errno || *ptr == start) { 584e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("'%s' is not a valid number.\n", what); 585e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 586e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 587e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 588e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 589e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 590e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* 591e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Stuff 'lr' according to the line range described by 'arg'. 592e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * The line range syntax is described by: 593e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 594e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * SRC[:SLN[+NUM|-ELN]] 595e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * FNC[@SRC][:SLN[+NUM|-ELN]] 596e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 597e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint parse_line_range_desc(const char *arg, struct line_range *lr) 598e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 599e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *range, *file, *name = strdup(arg); 600e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int err; 601e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 602e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!name) 603e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 604e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 605e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng lr->start = 0; 606e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng lr->end = INT_MAX; 607e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 608e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng range = strchr(name, ':'); 609e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (range) { 610e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *range++ = '\0'; 611e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 612e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng err = parse_line_num(&range, &lr->start, "start line"); 613e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (err) 614e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto err; 615e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 616e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*range == '+' || *range == '-') { 617e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char c = *range++; 618e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 619e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng err = parse_line_num(&range, &lr->end, "end line"); 620e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (err) 621e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto err; 622e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 623e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (c == '+') { 624e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng lr->end += lr->start; 625e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 626e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Adjust the number of lines here. 627e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * If the number of lines == 1, the 628e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * the end of line should be equal to 629e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * the start of line. 630e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 631e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng lr->end--; 632e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 633e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 634e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 635e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Line range is %d to %d\n", lr->start, lr->end); 636e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 637e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng err = -EINVAL; 638e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (lr->start > lr->end) { 639e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("Start line must be smaller" 640e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng " than end line.\n"); 641e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto err; 642e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 643e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*range != '\0') { 644e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("Tailing with invalid str '%s'.\n", range); 645e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto err; 646e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 647e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 648e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 649e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng file = strchr(name, '@'); 650e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (file) { 651e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *file = '\0'; 652e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng lr->file = strdup(++file); 653e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (lr->file == NULL) { 654e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng err = -ENOMEM; 655e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto err; 656e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 657e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng lr->function = name; 658e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else if (strchr(name, '.')) 659e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng lr->file = name; 660e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 661e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng lr->function = name; 662e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 663e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 664e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengerr: 665e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(name); 666e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return err; 667e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 668e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 669e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Check the name is good for event/group */ 670e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic bool check_event_name(const char *name) 671e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 672e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!isalpha(*name) && *name != '_') 673e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return false; 674e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (*++name != '\0') { 675e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!isalpha(*name) && !isdigit(*name) && *name != '_') 676e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return false; 677e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 678e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return true; 679e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 680e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 681e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Parse probepoint definition. */ 682e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) 683e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 684e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_probe_point *pp = &pev->point; 685e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *ptr, *tmp; 686e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char c, nc = 0; 687e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 688e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * <Syntax> 689e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * perf probe [EVENT=]SRC[:LN|;PTN] 690e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] 691e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 692e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * TODO:Group name support 693e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 694e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 695e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ptr = strpbrk(arg, ";=@+%"); 696e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ptr && *ptr == '=') { /* Event name */ 697e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *ptr = '\0'; 698e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp = ptr + 1; 699e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (strchr(arg, ':')) { 700e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("Group name is not supported yet.\n"); 701e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOTSUP; 702e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 703e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!check_event_name(arg)) { 704e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("%s is bad for event name -it must " 705e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "follow C symbol-naming rule.\n", arg); 706e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 707e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 708e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pev->event = strdup(arg); 709e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->event == NULL) 710e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 711e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pev->group = NULL; 712e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng arg = tmp; 713e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 714e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 715e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ptr = strpbrk(arg, ";:+@%"); 716e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ptr) { 717e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng nc = *ptr; 718e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *ptr++ = '\0'; 719e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 720e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 721e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp = strdup(arg); 722e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tmp == NULL) 723e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 724e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 725e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Check arg is function or file and copy it */ 726e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (strchr(tmp, '.')) /* File */ 727e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pp->file = tmp; 728e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else /* Function */ 729e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pp->function = tmp; 730e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 731e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Parse other options */ 732e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (ptr) { 733e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng arg = ptr; 734e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng c = nc; 735e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (c == ';') { /* Lazy pattern must be the last part */ 736e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pp->lazy_line = strdup(arg); 737e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->lazy_line == NULL) 738e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 739e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 740e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 741e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ptr = strpbrk(arg, ";:+@%"); 742e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ptr) { 743e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng nc = *ptr; 744e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *ptr++ = '\0'; 745e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 746e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng switch (c) { 747e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case ':': /* Line number */ 748e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pp->line = strtoul(arg, &tmp, 0); 749e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*tmp != '\0') { 750e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("There is non-digit char" 751e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng " in line number.\n"); 752e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 753e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 754e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 755e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case '+': /* Byte offset from a symbol */ 756e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pp->offset = strtoul(arg, &tmp, 0); 757e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*tmp != '\0') { 758e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("There is non-digit character" 759e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng " in offset.\n"); 760e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 761e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 762e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 763e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case '@': /* File name */ 764e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->file) { 765e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("SRC@SRC is not allowed.\n"); 766e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 767e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 768e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pp->file = strdup(arg); 769e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->file == NULL) 770e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 771e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 772e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case '%': /* Probe places */ 773e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (strcmp(arg, "return") == 0) { 774e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pp->retprobe = 1; 775e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else { /* Others not supported yet */ 776e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("%%%s is not supported.\n", arg); 777e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOTSUP; 778e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 779e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 780e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng default: /* Buggy case */ 781e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_err("This program has a bug at %s:%d.\n", 782e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng __FILE__, __LINE__); 783e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOTSUP; 784e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 785e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 786e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 787e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 788e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Exclusion check */ 789e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->lazy_line && pp->line) { 790e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("Lazy pattern can't be used with" 791e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng " line number.\n"); 792e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 793e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 794e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 795e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->lazy_line && pp->offset) { 796e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("Lazy pattern can't be used with offset.\n"); 797e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 798e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 799e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 800e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->line && pp->offset) { 801e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("Offset can't be used with line number.\n"); 802e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 803e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 804e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 805e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!pp->line && !pp->lazy_line && pp->file && !pp->function) { 806e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("File always requires line number or " 807e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "lazy pattern.\n"); 808e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 809e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 810e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 811e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->offset && !pp->function) { 812e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("Offset requires an entry function.\n"); 813e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 814e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 815e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 816e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->retprobe && !pp->function) { 817e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("Return probe requires an entry function.\n"); 818e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 819e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 820e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 821e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) { 822e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("Offset/Line/Lazy pattern can't be used with " 823e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "return probe.\n"); 824e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 825e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 826e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 827e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n", 828e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pp->function, pp->file, pp->line, pp->offset, pp->retprobe, 829e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pp->lazy_line); 830e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 831e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 832e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 833e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Parse perf-probe event argument */ 834e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) 835e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 836e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *tmp, *goodname; 837e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_probe_arg_field **fieldp; 838e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 839e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("parsing arg: %s into ", str); 840e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 841e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp = strchr(str, '='); 842e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tmp) { 843e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng arg->name = strndup(str, tmp - str); 844e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (arg->name == NULL) 845e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 846e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("name:%s ", arg->name); 847e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng str = tmp + 1; 848e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 849e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 850e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp = strchr(str, ':'); 851e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tmp) { /* Type setting */ 852e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *tmp = '\0'; 853e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng arg->type = strdup(tmp + 1); 854e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (arg->type == NULL) 855e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 856e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("type:%s ", arg->type); 857e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 858e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 859e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp = strpbrk(str, "-.["); 860e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!is_c_varname(str) || !tmp) { 861e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* A variable, register, symbol or special value */ 862e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng arg->var = strdup(str); 863e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (arg->var == NULL) 864e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 865e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("%s\n", arg->var); 866e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 867e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 868e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 869e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Structure fields or array element */ 870e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng arg->var = strndup(str, tmp - str); 871e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (arg->var == NULL) 872e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 873e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goodname = arg->var; 874e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("%s, ", arg->var); 875e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fieldp = &arg->field; 876e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 877e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng do { 878e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *fieldp = zalloc(sizeof(struct perf_probe_arg_field)); 879e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*fieldp == NULL) 880e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 881e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*tmp == '[') { /* Array */ 882e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng str = tmp; 883e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (*fieldp)->index = strtol(str + 1, &tmp, 0); 884e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (*fieldp)->ref = true; 885e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*tmp != ']' || tmp == str + 1) { 886e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("Array index must be a" 887e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng " number.\n"); 888e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 889e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 890e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp++; 891e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*tmp == '\0') 892e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp = NULL; 893e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else { /* Structure */ 894e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*tmp == '.') { 895e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng str = tmp + 1; 896e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (*fieldp)->ref = false; 897e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else if (tmp[1] == '>') { 898e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng str = tmp + 2; 899e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (*fieldp)->ref = true; 900e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else { 901e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("Argument parse error: %s\n", 902e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng str); 903e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 904e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 905e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp = strpbrk(str, "-.["); 906e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 907e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tmp) { 908e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (*fieldp)->name = strndup(str, tmp - str); 909e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if ((*fieldp)->name == NULL) 910e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 911e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*str != '[') 912e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goodname = (*fieldp)->name; 913e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref); 914e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fieldp = &(*fieldp)->next; 915e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 916e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } while (tmp); 917e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (*fieldp)->name = strdup(str); 918e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if ((*fieldp)->name == NULL) 919e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 920e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*str != '[') 921e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goodname = (*fieldp)->name; 922e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref); 923e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 924e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* If no name is specified, set the last field name (not array index)*/ 925e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!arg->name) { 926e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng arg->name = strdup(goodname); 927e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (arg->name == NULL) 928e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 929e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 930e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 931e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 932e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 933e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Parse perf-probe event command */ 934e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev) 935e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 936e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char **argv; 937e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int argc, i, ret = 0; 938e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 939e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng argv = argv_split(cmd, &argc); 940e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!argv) { 941e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Failed to split arguments.\n"); 942e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 943e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 944e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (argc - 1 > MAX_PROBE_ARGS) { 945e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("Too many probe arguments (%d).\n", argc - 1); 946e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ERANGE; 947e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 948e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 949e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Parse probe point */ 950e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = parse_perf_probe_point(argv[0], pev); 951e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 952e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 953e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 954e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Copy arguments and ensure return probe has no C argument */ 955e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pev->nargs = argc - 1; 956e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs); 957e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->args == NULL) { 958e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ENOMEM; 959e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 960e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 961e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < pev->nargs && ret >= 0; i++) { 962e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]); 963e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret >= 0 && 964e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng is_c_varname(pev->args[i].var) && pev->point.retprobe) { 965e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("You can't specify local variable for" 966e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng " kretprobe.\n"); 967e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -EINVAL; 968e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 969e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 970e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout: 971e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng argv_free(argv); 972e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 973e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 974e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 975e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 976e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Return true if this perf_probe_event requires debuginfo */ 977e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengbool perf_probe_event_need_dwarf(struct perf_probe_event *pev) 978e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 979e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i; 980e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 981e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->point.file || pev->point.line || pev->point.lazy_line) 982e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return true; 983e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 984e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < pev->nargs; i++) 985e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (is_c_varname(pev->args[i].var)) 986e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return true; 987e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 988e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return false; 989e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 990e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 991e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Parse probe_events event into struct probe_point */ 992e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int parse_probe_trace_command(const char *cmd, 993e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct probe_trace_event *tev) 994e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 995e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct probe_trace_point *tp = &tev->point; 996e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char pr; 997e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *p; 998e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret, i, argc; 999e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char **argv; 1000e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1001e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Parsing probe_events: %s\n", cmd); 1002e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng argv = argv_split(cmd, &argc); 1003e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!argv) { 1004e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Failed to split arguments.\n"); 1005e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 1006e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1007e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (argc < 2) { 1008e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("Too few probe arguments.\n"); 1009e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ERANGE; 1010e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 1011e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1012e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1013e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Scan event and group name. */ 1014e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]", 1015e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng &pr, (float *)(void *)&tev->group, 1016e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (float *)(void *)&tev->event); 1017e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret != 3) { 1018e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng semantic_error("Failed to parse event name: %s\n", argv[0]); 1019e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -EINVAL; 1020e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 1021e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1022e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr); 1023e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1024e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tp->retprobe = (pr == 'r'); 1025e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1026e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Scan function name and offset */ 1027e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = sscanf(argv[1], "%a[^+]+%lu", (float *)(void *)&tp->symbol, 1028e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng &tp->offset); 1029e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret == 1) 1030e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tp->offset = 0; 1031e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1032e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->nargs = argc - 2; 1033e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); 1034e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->args == NULL) { 1035e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ENOMEM; 1036e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 1037e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1038e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < tev->nargs; i++) { 1039e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng p = strchr(argv[i + 2], '='); 1040e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (p) /* We don't need which register is assigned. */ 1041e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *p++ = '\0'; 1042e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 1043e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng p = argv[i + 2]; 1044e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->args[i].name = strdup(argv[i + 2]); 1045e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* TODO: parse regs and offset */ 1046e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->args[i].value = strdup(p); 1047e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->args[i].name == NULL || tev->args[i].value == NULL) { 1048e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ENOMEM; 1049e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 1050e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1051e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1052e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = 0; 1053e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout: 1054e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng argv_free(argv); 1055e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1056e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1057e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1058e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Compose only probe arg */ 1059e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len) 1060e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1061e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_probe_arg_field *field = pa->field; 1062e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret; 1063e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *tmp = buf; 1064e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1065e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pa->name && pa->var) 1066e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var); 1067e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 1068e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var); 1069e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret <= 0) 1070e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1071e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp += ret; 1072e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng len -= ret; 1073e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1074e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (field) { 1075e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (field->name[0] == '[') 1076e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(tmp, len, "%s", field->name); 1077e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 1078e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(tmp, len, "%s%s", 1079e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng field->ref ? "->" : ".", field->name); 1080e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret <= 0) 1081e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1082e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp += ret; 1083e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng len -= ret; 1084e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng field = field->next; 1085e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1086e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1087e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pa->type) { 1088e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(tmp, len, ":%s", pa->type); 1089e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret <= 0) 1090e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1091e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp += ret; 1092e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng len -= ret; 1093e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1094e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1095e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return tmp - buf; 1096e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengerror: 1097e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Failed to synthesize perf probe argument: %s\n", 1098e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strerror(-ret)); 1099e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Compose only probe point (not argument) */ 1103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic char *synthesize_perf_probe_point(struct perf_probe_point *pp) 1104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *buf, *tmp; 1106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char offs[32] = "", line[32] = "", file[32] = ""; 1107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret, len; 1108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng buf = zalloc(MAX_CMDLEN); 1110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (buf == NULL) { 1111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ENOMEM; 1112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->offset) { 1115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(offs, 32, "+%lu", pp->offset); 1116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret <= 0) 1117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->line) { 1120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(line, 32, ":%d", pp->line); 1121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret <= 0) 1122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->file) { 1125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp = pp->file; 1126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng len = strlen(tmp); 1127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (len > 30) { 1128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp = strchr(pp->file + len - 30, '/'); 1129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp = tmp ? tmp + 1 : pp->file + len - 30; 1130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(file, 32, "@%s", tmp); 1132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret <= 0) 1133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->function) 1137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function, 1138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng offs, pp->retprobe ? "%return" : "", line, 1139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng file); 1140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 1141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line); 1142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret <= 0) 1143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return buf; 1146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengerror: 1147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Failed to synthesize perf probe point: %s\n", 1148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strerror(-ret)); 1149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (buf) 1150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(buf); 1151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 1152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#if 0 1155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengchar *synthesize_perf_probe_command(struct perf_probe_event *pev) 1156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *buf; 1158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i, len, ret; 1159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng buf = synthesize_perf_probe_point(&pev->point); 1161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!buf) 1162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 1163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng len = strlen(buf); 1165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < pev->nargs; i++) { 1166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s", 1167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pev->args[i].name); 1168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret <= 0) { 1169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(buf); 1170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 1171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng len += ret; 1173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return buf; 1176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#endif 1178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref, 1180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char **buf, size_t *buflen, 1181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int depth) 1182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret; 1184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ref->next) { 1185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng depth = __synthesize_probe_trace_arg_ref(ref->next, buf, 1186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng buflen, depth + 1); 1187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (depth < 0) 1188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 1189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset); 1192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng depth = ret; 1194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else { 1195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *buf += ret; 1196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *buflen -= ret; 1197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout: 1199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return depth; 1200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1202e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int synthesize_probe_trace_arg(struct probe_trace_arg *arg, 1204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *buf, size_t buflen) 1205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct probe_trace_arg_ref *ref = arg->ref; 1207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret, depth = 0; 1208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *tmp = buf; 1209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Argument name or separator */ 1211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (arg->name) 1212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(buf, buflen, " %s=", arg->name); 1213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 1214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(buf, buflen, " "); 1215e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1216e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1217e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng buf += ret; 1218e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng buflen -= ret; 1219e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1220e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Special case: @XXX */ 1221e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (arg->value[0] == '@' && arg->ref) 1222e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ref = ref->next; 1223e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1224e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Dereferencing arguments */ 1225e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ref) { 1226e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng depth = __synthesize_probe_trace_arg_ref(ref, &buf, 1227e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng &buflen, 1); 1228e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (depth < 0) 1229e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return depth; 1230e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1231e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1232e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Print argument value */ 1233e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (arg->value[0] == '@' && arg->ref) 1234e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(buf, buflen, "%s%+ld", arg->value, 1235e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng arg->ref->offset); 1236e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 1237e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(buf, buflen, "%s", arg->value); 1238e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1239e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1240e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng buf += ret; 1241e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng buflen -= ret; 1242e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1243e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Closing */ 1244e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (depth--) { 1245e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(buf, buflen, ")"); 1246e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1247e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1248e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng buf += ret; 1249e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng buflen -= ret; 1250e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1251e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Print argument type */ 1252e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (arg->type) { 1253e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(buf, buflen, ":%s", arg->type); 1254e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret <= 0) 1255e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1256e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng buf += ret; 1257e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1258e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1259e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return buf - tmp; 1260e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1261e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1262e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengchar *synthesize_probe_trace_command(struct probe_trace_event *tev) 1263e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1264e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct probe_trace_point *tp = &tev->point; 1265e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *buf; 1266e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i, len, ret; 1267e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1268e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng buf = zalloc(MAX_CMDLEN); 1269e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (buf == NULL) 1270e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 1271e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1272e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu", 1273e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tp->retprobe ? 'r' : 'p', 1274e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->group, tev->event, 1275e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tp->symbol, tp->offset); 1276e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (len <= 0) 1277e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1278e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1279e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < tev->nargs; i++) { 1280e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = synthesize_probe_trace_arg(&tev->args[i], buf + len, 1281e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng MAX_CMDLEN - len); 1282e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret <= 0) 1283e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1284e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng len += ret; 1285e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1286e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1287e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return buf; 1288e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengerror: 1289e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(buf); 1290e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 1291e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1292e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1293e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int convert_to_perf_probe_event(struct probe_trace_event *tev, 1294e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_probe_event *pev) 1295e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1296e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char buf[64] = ""; 1297e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i, ret; 1298e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1299e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Convert event/group name */ 1300e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pev->event = strdup(tev->event); 1301e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pev->group = strdup(tev->group); 1302e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->event == NULL || pev->group == NULL) 1303e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 1304e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1305e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Convert trace_point to probe_point */ 1306e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point); 1307e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1308e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1309e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1310e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Convert trace_arg to probe_arg */ 1311e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pev->nargs = tev->nargs; 1312e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs); 1313e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->args == NULL) 1314e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 1315e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < tev->nargs && ret >= 0; i++) { 1316e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->args[i].name) 1317e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pev->args[i].name = strdup(tev->args[i].name); 1318e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else { 1319e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = synthesize_probe_trace_arg(&tev->args[i], 1320e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng buf, 64); 1321e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pev->args[i].name = strdup(buf); 1322e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1323e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->args[i].name == NULL && ret >= 0) 1324e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ENOMEM; 1325e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1326e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1327e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1328e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng clear_perf_probe_event(pev); 1329e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1330e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1331e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1332e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1333e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid clear_perf_probe_event(struct perf_probe_event *pev) 1334e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1335e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_probe_point *pp = &pev->point; 1336e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_probe_arg_field *field, *next; 1337e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i; 1338e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1339e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->event) 1340e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(pev->event); 1341e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->group) 1342e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(pev->group); 1343e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->file) 1344e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(pp->file); 1345e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->function) 1346e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(pp->function); 1347e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pp->lazy_line) 1348e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(pp->lazy_line); 1349e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < pev->nargs; i++) { 1350e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->args[i].name) 1351e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(pev->args[i].name); 1352e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->args[i].var) 1353e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(pev->args[i].var); 1354e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->args[i].type) 1355e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(pev->args[i].type); 1356e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng field = pev->args[i].field; 1357e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (field) { 1358e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng next = field->next; 1359e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (field->name) 1360e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(field->name); 1361e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(field); 1362e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng field = next; 1363e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1364e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1365e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->args) 1366e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(pev->args); 1367e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memset(pev, 0, sizeof(*pev)); 1368e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1369e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1370e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void clear_probe_trace_event(struct probe_trace_event *tev) 1371e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1372e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct probe_trace_arg_ref *ref, *next; 1373e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i; 1374e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1375e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->event) 1376e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(tev->event); 1377e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->group) 1378e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(tev->group); 1379e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->point.symbol) 1380e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(tev->point.symbol); 1381e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < tev->nargs; i++) { 1382e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->args[i].name) 1383e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(tev->args[i].name); 1384e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->args[i].value) 1385e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(tev->args[i].value); 1386e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->args[i].type) 1387e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(tev->args[i].type); 1388e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ref = tev->args[i].ref; 1389e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (ref) { 1390e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng next = ref->next; 1391e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(ref); 1392e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ref = next; 1393e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1394e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1395e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->args) 1396e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(tev->args); 1397e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memset(tev, 0, sizeof(*tev)); 1398e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1399e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1400e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int open_kprobe_events(bool readwrite) 1401e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1402e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char buf[PATH_MAX]; 1403e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *__debugfs; 1404e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret; 1405e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1406e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng __debugfs = debugfs_find_mountpoint(); 1407e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (__debugfs == NULL) { 1408e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Debugfs is not mounted.\n"); 1409e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOENT; 1410e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1411e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1412e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(buf, PATH_MAX, "%stracing/kprobe_events", __debugfs); 1413e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret >= 0) { 1414e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Opening %s write=%d\n", buf, readwrite); 1415e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (readwrite && !probe_event_dry_run) 1416e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = open(buf, O_RDWR, O_APPEND); 1417e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 1418e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = open(buf, O_RDONLY, 0); 1419e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1420e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1421e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) { 1422e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (errno == ENOENT) 1423e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("kprobe_events file does not exist - please" 1424e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng " rebuild kernel with CONFIG_KPROBE_EVENT.\n"); 1425e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 1426e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Failed to open kprobe_events file: %s\n", 1427e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strerror(errno)); 1428e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1429e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1430e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1431e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1432e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Get raw string list of current kprobe_events */ 1433e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct strlist *get_probe_trace_command_rawlist(int fd) 1434e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1435e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret, idx; 1436e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng FILE *fp; 1437e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char buf[MAX_CMDLEN]; 1438e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *p; 1439e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct strlist *sl; 1440e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1441e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sl = strlist__new(true, NULL); 1442e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1443e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fp = fdopen(dup(fd), "r"); 1444e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (!feof(fp)) { 1445e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng p = fgets(buf, MAX_CMDLEN, fp); 1446e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!p) 1447e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 1448e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1449e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng idx = strlen(p) - 1; 1450e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (p[idx] == '\n') 1451e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng p[idx] = '\0'; 1452e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = strlist__add(sl, buf); 1453e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) { 1454e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("strlist__add failed: %s\n", strerror(-ret)); 1455e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlist__delete(sl); 1456e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 1457e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1458e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1459e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fclose(fp); 1460e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1461e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return sl; 1462e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1463e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1464e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Show an event */ 1465e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int show_perf_probe_event(struct perf_probe_event *pev) 1466e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1467e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i, ret; 1468e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char buf[128]; 1469e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *place; 1470e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1471e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Synthesize only event probe point */ 1472e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng place = synthesize_perf_probe_point(&pev->point); 1473e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!place) 1474e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 1475e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1476e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event); 1477e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1478e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1479e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1480e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf(" %-20s (on %s", buf, place); 1481e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1482e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->nargs > 0) { 1483e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf(" with"); 1484e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < pev->nargs; i++) { 1485e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = synthesize_perf_probe_arg(&pev->args[i], 1486e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng buf, 128); 1487e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1488e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 1489e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf(" %s", buf); 1490e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1491e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1492e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf(")\n"); 1493e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(place); 1494e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1495e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1496e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1497e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* List up current perf-probe events */ 1498e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint show_perf_probe_events(void) 1499e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1500e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int fd, ret; 1501e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct probe_trace_event tev; 1502e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_probe_event pev; 1503e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct strlist *rawlist; 1504e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct str_node *ent; 1505e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1506e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng setup_pager(); 1507e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = init_vmlinux(); 1508e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1509e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1510e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1511e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memset(&tev, 0, sizeof(tev)); 1512e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memset(&pev, 0, sizeof(pev)); 1513e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1514e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fd = open_kprobe_events(false); 1515e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (fd < 0) 1516e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return fd; 1517e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1518e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rawlist = get_probe_trace_command_rawlist(fd); 1519e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(fd); 1520e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!rawlist) 1521e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOENT; 1522e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1523e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlist__for_each(ent, rawlist) { 1524e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = parse_probe_trace_command(ent->s, &tev); 1525e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret >= 0) { 1526e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = convert_to_perf_probe_event(&tev, &pev); 1527e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret >= 0) 1528e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = show_perf_probe_event(&pev); 1529e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1530e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng clear_perf_probe_event(&pev); 1531e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng clear_probe_trace_event(&tev); 1532e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1533e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 1534e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1535e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlist__delete(rawlist); 1536e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1537e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1538e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1539e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1540e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Get current perf-probe event names */ 1541e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct strlist *get_probe_trace_event_names(int fd, bool include_group) 1542e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1543e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char buf[128]; 1544e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct strlist *sl, *rawlist; 1545e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct str_node *ent; 1546e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct probe_trace_event tev; 1547e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret = 0; 1548e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1549e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memset(&tev, 0, sizeof(tev)); 1550e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rawlist = get_probe_trace_command_rawlist(fd); 1551e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sl = strlist__new(true, NULL); 1552e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlist__for_each(ent, rawlist) { 1553e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = parse_probe_trace_command(ent->s, &tev); 1554e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1555e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 1556e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (include_group) { 1557e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(buf, 128, "%s:%s", tev.group, 1558e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev.event); 1559e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret >= 0) 1560e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = strlist__add(sl, buf); 1561e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else 1562e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = strlist__add(sl, tev.event); 1563e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng clear_probe_trace_event(&tev); 1564e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1565e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 1566e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1567e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlist__delete(rawlist); 1568e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1569e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) { 1570e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlist__delete(sl); 1571e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 1572e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1573e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return sl; 1574e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1575e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1576e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int write_probe_trace_event(int fd, struct probe_trace_event *tev) 1577e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1578e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret = 0; 1579e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *buf = synthesize_probe_trace_command(tev); 1580e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1581e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!buf) { 1582e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Failed to synthesize probe trace event.\n"); 1583e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 1584e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1585e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1586e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Writing event: %s\n", buf); 1587e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!probe_event_dry_run) { 1588e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = write(fd, buf, strlen(buf)); 1589e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret <= 0) 1590e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Failed to write event: %s\n", 1591e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strerror(errno)); 1592e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1593e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(buf); 1594e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1595e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1596e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1597e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int get_new_event_name(char *buf, size_t len, const char *base, 1598e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct strlist *namelist, bool allow_suffix) 1599e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1600e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i, ret; 1601e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1602e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Try no suffix */ 1603e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(buf, len, "%s", base); 1604e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) { 1605e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("snprintf() failed: %s\n", strerror(-ret)); 1606e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1607e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1608e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!strlist__has_entry(namelist, buf)) 1609e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 1610e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1611e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!allow_suffix) { 1612e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Error: event \"%s\" already exists. " 1613e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "(Use -f to force duplicates.)\n", base); 1614e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EEXIST; 1615e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1616e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1617e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Try to add suffix */ 1618e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 1; i < MAX_EVENT_INDEX; i++) { 1619e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(buf, len, "%s_%d", base, i); 1620e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) { 1621e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("snprintf() failed: %s\n", strerror(-ret)); 1622e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1623e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1624e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!strlist__has_entry(namelist, buf)) 1625e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 1626e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1627e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (i == MAX_EVENT_INDEX) { 1628e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Too many events are on the same function.\n"); 1629e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ERANGE; 1630e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1631e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1632e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1633e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1634e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1635e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int __add_probe_trace_events(struct perf_probe_event *pev, 1636e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct probe_trace_event *tevs, 1637e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ntevs, bool allow_suffix) 1638e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1639e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i, fd, ret; 1640e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct probe_trace_event *tev = NULL; 1641e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char buf[64]; 1642e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *event, *group; 1643e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct strlist *namelist; 1644e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1645e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fd = open_kprobe_events(true); 1646e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (fd < 0) 1647e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return fd; 1648e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Get current event names */ 1649e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng namelist = get_probe_trace_event_names(fd, false); 1650e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!namelist) { 1651e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Failed to get current event list.\n"); 1652e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EIO; 1653e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1654e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1655e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = 0; 1656e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":"); 1657e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < ntevs; i++) { 1658e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev = &tevs[i]; 1659e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->event) 1660e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event = pev->event; 1661e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 1662e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->point.function) 1663e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event = pev->point.function; 1664e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 1665e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event = tev->point.symbol; 1666e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->group) 1667e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng group = pev->group; 1668e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 1669e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng group = PERFPROBE_GROUP; 1670e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1671e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Get an unused new event name */ 1672e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = get_new_event_name(buf, 64, event, 1673e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng namelist, allow_suffix); 1674e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1675e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 1676e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event = buf; 1677e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1678e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->event = strdup(event); 1679e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->group = strdup(group); 1680e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->event == NULL || tev->group == NULL) { 1681e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ENOMEM; 1682e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 1683e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1684e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = write_probe_trace_event(fd, tev); 1685e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1686e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 1687e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Add added event name to namelist */ 1688e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlist__add(namelist, event); 1689e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1690e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Trick here - save current event/group */ 1691e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event = pev->event; 1692e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng group = pev->group; 1693e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pev->event = tev->event; 1694e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pev->group = tev->group; 1695e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng show_perf_probe_event(pev); 1696e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Trick here - restore current event/group */ 1697e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pev->event = (char *)event; 1698e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pev->group = (char *)group; 1699e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1700e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 1701e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Probes after the first probe which comes from same 1702e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * user input are always allowed to add suffix, because 1703e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * there might be several addresses corresponding to 1704e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * one code line. 1705e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 1706e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng allow_suffix = true; 1707e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1708e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1709e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret >= 0) { 1710e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Show how to use the event. */ 1711e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("\nYou can now use it on all perf tools, such as:\n\n"); 1712e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 1713e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->event); 1714e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1715e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1716e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlist__delete(namelist); 1717e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(fd); 1718e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1719e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1720e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1721e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int convert_to_probe_trace_events(struct perf_probe_event *pev, 1722e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct probe_trace_event **tevs, 1723e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int max_tevs, const char *module) 1724e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1725e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct symbol *sym; 1726e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret = 0, i; 1727e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct probe_trace_event *tev; 1728e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1729e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Convert perf_probe_event with debuginfo */ 1730e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module); 1731e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret != 0) 1732e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1733e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1734e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Allocate trace event buffer */ 1735e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev = *tevs = zalloc(sizeof(struct probe_trace_event)); 1736e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev == NULL) 1737e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 1738e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1739e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Copy parameters */ 1740e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->point.symbol = strdup(pev->point.function); 1741e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->point.symbol == NULL) { 1742e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ENOMEM; 1743e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1744e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1745e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->point.offset = pev->point.offset; 1746e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->point.retprobe = pev->point.retprobe; 1747e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->nargs = pev->nargs; 1748e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->nargs) { 1749e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->args = zalloc(sizeof(struct probe_trace_arg) 1750e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * tev->nargs); 1751e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->args == NULL) { 1752e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ENOMEM; 1753e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1754e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1755e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < tev->nargs; i++) { 1756e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->args[i].name) { 1757e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->args[i].name = strdup(pev->args[i].name); 1758e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->args[i].name == NULL) { 1759e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ENOMEM; 1760e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1761e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1762e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1763e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->args[i].value = strdup(pev->args[i].var); 1764e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->args[i].value == NULL) { 1765e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ENOMEM; 1766e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1767e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1768e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pev->args[i].type) { 1769e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->args[i].type = strdup(pev->args[i].type); 1770e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tev->args[i].type == NULL) { 1771e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ENOMEM; 1772e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1773e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1774e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1775e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1776e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1777e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1778e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Currently just checking function name from symbol map */ 1779e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sym = __find_kernel_function_by_name(tev->point.symbol, NULL); 1780e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!sym) { 1781e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Kernel symbol \'%s\' not found.\n", 1782e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tev->point.symbol); 1783e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ENOENT; 1784e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1785e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1786e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1787e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 1; 1788e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengerror: 1789e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng clear_probe_trace_event(tev); 1790e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(tev); 1791e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *tevs = NULL; 1792e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1793e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1794e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1795e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct __event_package { 1796e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_probe_event *pev; 1797e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct probe_trace_event *tevs; 1798e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ntevs; 1799e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 1800e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1801e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 1802e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int max_tevs, const char *module, bool force_add) 1803e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1804e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i, j, ret; 1805e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct __event_package *pkgs; 1806e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1807e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pkgs = zalloc(sizeof(struct __event_package) * npevs); 1808e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pkgs == NULL) 1809e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 1810e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1811e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Init vmlinux path */ 1812e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = init_vmlinux(); 1813e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) { 1814e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(pkgs); 1815e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1816e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1817e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1818e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Loop 1: convert all events */ 1819e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < npevs; i++) { 1820e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pkgs[i].pev = &pevs[i]; 1821e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Convert with or without debuginfo */ 1822e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = convert_to_probe_trace_events(pkgs[i].pev, 1823e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng &pkgs[i].tevs, 1824e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng max_tevs, 1825e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng module); 1826e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1827e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto end; 1828e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pkgs[i].ntevs = ret; 1829e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1830e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1831e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Loop 2: add all events */ 1832e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < npevs; i++) { 1833e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs, 1834e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pkgs[i].ntevs, force_add); 1835e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1836e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 1837e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1838e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengend: 1839e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Loop 3: cleanup and free trace events */ 1840e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < npevs; i++) { 1841e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (j = 0; j < pkgs[i].ntevs; j++) 1842e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng clear_probe_trace_event(&pkgs[i].tevs[j]); 1843e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(pkgs[i].tevs); 1844e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1845e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(pkgs); 1846e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1847e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1848e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1849e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1850e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int __del_trace_probe_event(int fd, struct str_node *ent) 1851e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1852e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *p; 1853e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char buf[128]; 1854e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret; 1855e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1856e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Convert from perf-probe event to trace-probe event */ 1857e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(buf, 128, "-:%s", ent->s); 1858e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1859e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1860e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1861e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng p = strchr(buf + 2, ':'); 1862e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!p) { 1863e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Internal error: %s should have ':' but not.\n", 1864e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ent->s); 1865e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ENOTSUP; 1866e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1867e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1868e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *p = '/'; 1869e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1870e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Writing event: %s\n", buf); 1871e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = write(fd, buf, strlen(buf)); 1872e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1873e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto error; 1874e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1875e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("Remove event: %s\n", ent->s); 1876e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 1877e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengerror: 1878e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Failed to delete event: %s\n", strerror(-ret)); 1879e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1880e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1881e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1882e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int del_trace_probe_event(int fd, const char *group, 1883e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *event, struct strlist *namelist) 1884e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1885e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char buf[128]; 1886e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct str_node *ent, *n; 1887e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int found = 0, ret = 0; 1888e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1889e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = e_snprintf(buf, 128, "%s:%s", group, event); 1890e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) { 1891e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_err("Failed to copy event.\n"); 1892e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1893e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1894e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1895e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (strpbrk(buf, "*?")) { /* Glob-exp */ 1896e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlist__for_each_safe(ent, n, namelist) 1897e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (strglobmatch(ent->s, buf)) { 1898e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng found++; 1899e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = __del_trace_probe_event(fd, ent); 1900e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1901e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 1902e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlist__remove(namelist, ent); 1903e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1904e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else { 1905e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ent = strlist__find(namelist, buf); 1906e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ent) { 1907e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng found++; 1908e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = __del_trace_probe_event(fd, ent); 1909e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret >= 0) 1910e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlist__remove(namelist, ent); 1911e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1912e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1913e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (found == 0 && ret >= 0) 1914e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_info("Info: Event \"%s\" does not exist.\n", buf); 1915e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1916e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1917e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1918e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1919e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint del_perf_probe_events(struct strlist *dellist) 1920e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1921e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int fd, ret = 0; 1922e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *group, *event; 1923e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *p, *str; 1924e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct str_node *ent; 1925e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct strlist *namelist; 1926e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1927e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fd = open_kprobe_events(true); 1928e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (fd < 0) 1929e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return fd; 1930e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1931e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Get current event names */ 1932e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng namelist = get_probe_trace_event_names(fd, true); 1933e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (namelist == NULL) 1934e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 1935e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1936e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlist__for_each(ent, dellist) { 1937e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng str = strdup(ent->s); 1938e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (str == NULL) { 1939e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = -ENOMEM; 1940e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 1941e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1942e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Parsing: %s\n", str); 1943e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng p = strchr(str, ':'); 1944e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (p) { 1945e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng group = str; 1946e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *p = '\0'; 1947e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event = p + 1; 1948e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else { 1949e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng group = "*"; 1950e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event = str; 1951e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1952e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Group: %s, Event: %s\n", group, event); 1953e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = del_trace_probe_event(fd, group, event, namelist); 1954e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(str); 1955e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1956e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 1957e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1958e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlist__delete(namelist); 1959e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(fd); 1960e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1961e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1962e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1963e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* TODO: don't use a global variable for filter ... */ 1964e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct strfilter *available_func_filter; 1965e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1966e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* 1967e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * If a symbol corresponds to a function with global binding and 1968e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * matches filter return 0. For all others return 1. 1969e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 1970e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int filter_available_functions(struct map *map __unused, 1971e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct symbol *sym) 1972e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1973e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (sym->binding == STB_GLOBAL && 1974e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strfilter__compare(available_func_filter, sym->name)) 1975e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 1976e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 1; 1977e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 1978e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1979e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint show_available_funcs(const char *module, struct strfilter *_filter) 1980e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 1981e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *map; 1982e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret; 1983e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1984e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng setup_pager(); 1985e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1986e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = init_vmlinux(); 1987e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 1988e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ret; 1989e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 1990e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map = kernel_get_module_map(module); 1991e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!map) { 1992e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_err("Failed to find %s map.\n", (module) ? : "kernel"); 1993e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 1994e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 1995e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng available_func_filter = _filter; 1996e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (map__load(map, filter_available_functions)) { 1997e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_err("Failed to load map.\n"); 1998e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -EINVAL; 1999e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 2000e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!dso__sorted_by_name(map->dso, map->type)) 2001e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dso__sort_by_name(map->dso, map->type); 2002e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 2003e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dso__fprintf_symbols_by_name(map->dso, map->type, stdout); 2004e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 2005e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 2006