150656eecSMasami Hiramatsu /* 20e60836bSSrikar Dronamraju * probe-event.c : perf-probe definition to probe_events format converter 350656eecSMasami Hiramatsu * 450656eecSMasami Hiramatsu * Written by Masami Hiramatsu <mhiramat@redhat.com> 550656eecSMasami Hiramatsu * 650656eecSMasami Hiramatsu * This program is free software; you can redistribute it and/or modify 750656eecSMasami Hiramatsu * it under the terms of the GNU General Public License as published by 850656eecSMasami Hiramatsu * the Free Software Foundation; either version 2 of the License, or 950656eecSMasami Hiramatsu * (at your option) any later version. 1050656eecSMasami Hiramatsu * 1150656eecSMasami Hiramatsu * This program is distributed in the hope that it will be useful, 1250656eecSMasami Hiramatsu * but WITHOUT ANY WARRANTY; without even the implied warranty of 1350656eecSMasami Hiramatsu * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1450656eecSMasami Hiramatsu * GNU General Public License for more details. 1550656eecSMasami Hiramatsu * 1650656eecSMasami Hiramatsu * You should have received a copy of the GNU General Public License 1750656eecSMasami Hiramatsu * along with this program; if not, write to the Free Software 1850656eecSMasami Hiramatsu * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 1950656eecSMasami Hiramatsu * 2050656eecSMasami Hiramatsu */ 2150656eecSMasami Hiramatsu 2250656eecSMasami Hiramatsu #include <sys/utsname.h> 2350656eecSMasami Hiramatsu #include <sys/types.h> 2450656eecSMasami Hiramatsu #include <sys/stat.h> 2550656eecSMasami Hiramatsu #include <fcntl.h> 2650656eecSMasami Hiramatsu #include <errno.h> 2750656eecSMasami Hiramatsu #include <stdio.h> 2850656eecSMasami Hiramatsu #include <unistd.h> 2950656eecSMasami Hiramatsu #include <stdlib.h> 3050656eecSMasami Hiramatsu #include <string.h> 314de189feSMasami Hiramatsu #include <stdarg.h> 324de189feSMasami Hiramatsu #include <limits.h> 33e80711caSMasami Hiramatsu #include <elf.h> 3450656eecSMasami Hiramatsu 3531facc5fSMasami Hiramatsu #include "util.h" 3650656eecSMasami Hiramatsu #include "event.h" 374de189feSMasami Hiramatsu #include "strlist.h" 3850656eecSMasami Hiramatsu #include "debug.h" 3972041334SMasami Hiramatsu #include "cache.h" 40631c9defSMasami Hiramatsu #include "color.h" 41e0faa8d3SMasami Hiramatsu #include "symbol.h" 42e0faa8d3SMasami Hiramatsu #include "thread.h" 43553873e1SBorislav Petkov #include <api/fs/debugfs.h> 441d037ca1SIrina Tirdea #include "trace-event.h" /* For __maybe_unused */ 4550656eecSMasami Hiramatsu #include "probe-event.h" 464235b045SMasami Hiramatsu #include "probe-finder.h" 47225466f1SSrikar Dronamraju #include "session.h" 4850656eecSMasami Hiramatsu 4950656eecSMasami Hiramatsu #define MAX_CMDLEN 256 5050656eecSMasami Hiramatsu #define PERFPROBE_GROUP "probe" 5150656eecSMasami Hiramatsu 52f4d7da49SMasami Hiramatsu bool probe_event_dry_run; /* Dry run flag */ 53f4d7da49SMasami Hiramatsu 54146a1439SMasami Hiramatsu #define semantic_error(msg ...) pr_err("Semantic error :" msg) 5550656eecSMasami Hiramatsu 564de189feSMasami Hiramatsu /* If there is no space to write, returns -E2BIG. */ 574de189feSMasami Hiramatsu static int e_snprintf(char *str, size_t size, const char *format, ...) 5884988450SMasami Hiramatsu __attribute__((format(printf, 3, 4))); 5984988450SMasami Hiramatsu 6084988450SMasami Hiramatsu static int e_snprintf(char *str, size_t size, const char *format, ...) 614de189feSMasami Hiramatsu { 624de189feSMasami Hiramatsu int ret; 634de189feSMasami Hiramatsu va_list ap; 644de189feSMasami Hiramatsu va_start(ap, format); 654de189feSMasami Hiramatsu ret = vsnprintf(str, size, format, ap); 664de189feSMasami Hiramatsu va_end(ap); 674de189feSMasami Hiramatsu if (ret >= (int)size) 684de189feSMasami Hiramatsu ret = -E2BIG; 694de189feSMasami Hiramatsu return ret; 704de189feSMasami Hiramatsu } 714de189feSMasami Hiramatsu 724b4da7f7SMasami Hiramatsu static char *synthesize_perf_probe_point(struct perf_probe_point *pp); 73225466f1SSrikar Dronamraju static int convert_name_to_addr(struct perf_probe_event *pev, 74225466f1SSrikar Dronamraju const char *exec); 75981d05adSMasami Hiramatsu static void clear_probe_trace_event(struct probe_trace_event *tev); 76*ee45b6c2SMasami Hiramatsu static struct machine *host_machine; 77e0faa8d3SMasami Hiramatsu 78469b9b88SMasami Hiramatsu /* Initialize symbol maps and path of vmlinux/modules */ 79*ee45b6c2SMasami Hiramatsu static int init_symbol_maps(bool user_only) 80e0faa8d3SMasami Hiramatsu { 81146a1439SMasami Hiramatsu int ret; 82146a1439SMasami Hiramatsu 83e0faa8d3SMasami Hiramatsu symbol_conf.sort_by_name = true; 84146a1439SMasami Hiramatsu ret = symbol__init(); 85146a1439SMasami Hiramatsu if (ret < 0) { 86146a1439SMasami Hiramatsu pr_debug("Failed to init symbol map.\n"); 87146a1439SMasami Hiramatsu goto out; 88146a1439SMasami Hiramatsu } 89e0faa8d3SMasami Hiramatsu 90*ee45b6c2SMasami Hiramatsu if (host_machine || user_only) /* already initialized */ 91*ee45b6c2SMasami Hiramatsu return 0; 92d28c6223SArnaldo Carvalho de Melo 93*ee45b6c2SMasami Hiramatsu if (symbol_conf.vmlinux_name) 94*ee45b6c2SMasami Hiramatsu pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name); 95*ee45b6c2SMasami Hiramatsu 96*ee45b6c2SMasami Hiramatsu host_machine = machine__new_host(); 97*ee45b6c2SMasami Hiramatsu if (!host_machine) { 98*ee45b6c2SMasami Hiramatsu pr_debug("machine__new_host() failed.\n"); 99*ee45b6c2SMasami Hiramatsu symbol__exit(); 100*ee45b6c2SMasami Hiramatsu ret = -1; 101469b9b88SMasami Hiramatsu } 102146a1439SMasami Hiramatsu out: 103146a1439SMasami Hiramatsu if (ret < 0) 104146a1439SMasami Hiramatsu pr_warning("Failed to init vmlinux path.\n"); 105146a1439SMasami Hiramatsu return ret; 106e0faa8d3SMasami Hiramatsu } 107e0faa8d3SMasami Hiramatsu 108*ee45b6c2SMasami Hiramatsu static void exit_symbol_maps(void) 109*ee45b6c2SMasami Hiramatsu { 110*ee45b6c2SMasami Hiramatsu if (host_machine) { 111*ee45b6c2SMasami Hiramatsu machine__delete(host_machine); 112*ee45b6c2SMasami Hiramatsu host_machine = NULL; 113*ee45b6c2SMasami Hiramatsu } 114*ee45b6c2SMasami Hiramatsu symbol__exit(); 115*ee45b6c2SMasami Hiramatsu } 116*ee45b6c2SMasami Hiramatsu 117469b9b88SMasami Hiramatsu static struct symbol *__find_kernel_function_by_name(const char *name, 118469b9b88SMasami Hiramatsu struct map **mapp) 119e0faa8d3SMasami Hiramatsu { 120*ee45b6c2SMasami Hiramatsu return machine__find_kernel_function_by_name(host_machine, name, mapp, 121469b9b88SMasami Hiramatsu NULL); 122e0faa8d3SMasami Hiramatsu } 123469b9b88SMasami Hiramatsu 124e80711caSMasami Hiramatsu static struct map *kernel_get_module_map(const char *module) 125e80711caSMasami Hiramatsu { 126e80711caSMasami Hiramatsu struct rb_node *nd; 127*ee45b6c2SMasami Hiramatsu struct map_groups *grp = &host_machine->kmaps; 128e80711caSMasami Hiramatsu 12914a8fd7cSMasami Hiramatsu /* A file path -- this is an offline module */ 13014a8fd7cSMasami Hiramatsu if (module && strchr(module, '/')) 131*ee45b6c2SMasami Hiramatsu return machine__new_module(host_machine, 0, module); 13214a8fd7cSMasami Hiramatsu 133e80711caSMasami Hiramatsu if (!module) 134e80711caSMasami Hiramatsu module = "kernel"; 135e80711caSMasami Hiramatsu 136e80711caSMasami Hiramatsu for (nd = rb_first(&grp->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) { 137e80711caSMasami Hiramatsu struct map *pos = rb_entry(nd, struct map, rb_node); 138e80711caSMasami Hiramatsu if (strncmp(pos->dso->short_name + 1, module, 139e80711caSMasami Hiramatsu pos->dso->short_name_len - 2) == 0) { 140e80711caSMasami Hiramatsu return pos; 141e80711caSMasami Hiramatsu } 142e80711caSMasami Hiramatsu } 143e80711caSMasami Hiramatsu return NULL; 144e80711caSMasami Hiramatsu } 145e80711caSMasami Hiramatsu 146e80711caSMasami Hiramatsu static struct dso *kernel_get_module_dso(const char *module) 147469b9b88SMasami Hiramatsu { 148469b9b88SMasami Hiramatsu struct dso *dso; 149fd930ff9SFranck Bui-Huu struct map *map; 150fd930ff9SFranck Bui-Huu const char *vmlinux_name; 151469b9b88SMasami Hiramatsu 152469b9b88SMasami Hiramatsu if (module) { 153*ee45b6c2SMasami Hiramatsu list_for_each_entry(dso, &host_machine->kernel_dsos, node) { 154469b9b88SMasami Hiramatsu if (strncmp(dso->short_name + 1, module, 155469b9b88SMasami Hiramatsu dso->short_name_len - 2) == 0) 156469b9b88SMasami Hiramatsu goto found; 157469b9b88SMasami Hiramatsu } 158469b9b88SMasami Hiramatsu pr_debug("Failed to find module %s.\n", module); 159469b9b88SMasami Hiramatsu return NULL; 160fd930ff9SFranck Bui-Huu } 161fd930ff9SFranck Bui-Huu 162*ee45b6c2SMasami Hiramatsu map = host_machine->vmlinux_maps[MAP__FUNCTION]; 163fd930ff9SFranck Bui-Huu dso = map->dso; 164fd930ff9SFranck Bui-Huu 165fd930ff9SFranck Bui-Huu vmlinux_name = symbol_conf.vmlinux_name; 166fd930ff9SFranck Bui-Huu if (vmlinux_name) { 1675230fb7dSArnaldo Carvalho de Melo if (dso__load_vmlinux(dso, map, vmlinux_name, false, NULL) <= 0) 168fd930ff9SFranck Bui-Huu return NULL; 169469b9b88SMasami Hiramatsu } else { 170c3a34e06SFranck Bui-Huu if (dso__load_vmlinux_path(dso, map, NULL) <= 0) { 171469b9b88SMasami Hiramatsu pr_debug("Failed to load kernel map.\n"); 172469b9b88SMasami Hiramatsu return NULL; 173469b9b88SMasami Hiramatsu } 174469b9b88SMasami Hiramatsu } 175469b9b88SMasami Hiramatsu found: 176e80711caSMasami Hiramatsu return dso; 177e80711caSMasami Hiramatsu } 178e80711caSMasami Hiramatsu 179e80711caSMasami Hiramatsu const char *kernel_get_module_path(const char *module) 180e80711caSMasami Hiramatsu { 181e80711caSMasami Hiramatsu struct dso *dso = kernel_get_module_dso(module); 182e80711caSMasami Hiramatsu return (dso) ? dso->long_name : NULL; 183469b9b88SMasami Hiramatsu } 184469b9b88SMasami Hiramatsu 185fb7345bbSMasami Hiramatsu static int convert_exec_to_group(const char *exec, char **result) 186fb7345bbSMasami Hiramatsu { 187fb7345bbSMasami Hiramatsu char *ptr1, *ptr2, *exec_copy; 188fb7345bbSMasami Hiramatsu char buf[64]; 189fb7345bbSMasami Hiramatsu int ret; 190fb7345bbSMasami Hiramatsu 191fb7345bbSMasami Hiramatsu exec_copy = strdup(exec); 192fb7345bbSMasami Hiramatsu if (!exec_copy) 193fb7345bbSMasami Hiramatsu return -ENOMEM; 194fb7345bbSMasami Hiramatsu 195fb7345bbSMasami Hiramatsu ptr1 = basename(exec_copy); 196fb7345bbSMasami Hiramatsu if (!ptr1) { 197fb7345bbSMasami Hiramatsu ret = -EINVAL; 198fb7345bbSMasami Hiramatsu goto out; 199fb7345bbSMasami Hiramatsu } 200fb7345bbSMasami Hiramatsu 201fb7345bbSMasami Hiramatsu ptr2 = strpbrk(ptr1, "-._"); 202fb7345bbSMasami Hiramatsu if (ptr2) 203fb7345bbSMasami Hiramatsu *ptr2 = '\0'; 204fb7345bbSMasami Hiramatsu ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1); 205fb7345bbSMasami Hiramatsu if (ret < 0) 206fb7345bbSMasami Hiramatsu goto out; 207fb7345bbSMasami Hiramatsu 208fb7345bbSMasami Hiramatsu *result = strdup(buf); 209fb7345bbSMasami Hiramatsu ret = *result ? 0 : -ENOMEM; 210fb7345bbSMasami Hiramatsu 211fb7345bbSMasami Hiramatsu out: 212fb7345bbSMasami Hiramatsu free(exec_copy); 213fb7345bbSMasami Hiramatsu return ret; 214fb7345bbSMasami Hiramatsu } 215fb7345bbSMasami Hiramatsu 216225466f1SSrikar Dronamraju static int convert_to_perf_probe_point(struct probe_trace_point *tp, 217225466f1SSrikar Dronamraju struct perf_probe_point *pp) 218225466f1SSrikar Dronamraju { 219225466f1SSrikar Dronamraju pp->function = strdup(tp->symbol); 220225466f1SSrikar Dronamraju 221225466f1SSrikar Dronamraju if (pp->function == NULL) 222225466f1SSrikar Dronamraju return -ENOMEM; 223225466f1SSrikar Dronamraju 224225466f1SSrikar Dronamraju pp->offset = tp->offset; 225225466f1SSrikar Dronamraju pp->retprobe = tp->retprobe; 226225466f1SSrikar Dronamraju 227225466f1SSrikar Dronamraju return 0; 228225466f1SSrikar Dronamraju } 229225466f1SSrikar Dronamraju 23089fe808aSIngo Molnar #ifdef HAVE_DWARF_SUPPORT 231ff741783SMasami Hiramatsu /* Open new debuginfo of given module */ 232ff741783SMasami Hiramatsu static struct debuginfo *open_debuginfo(const char *module) 233469b9b88SMasami Hiramatsu { 23414a8fd7cSMasami Hiramatsu const char *path; 23514a8fd7cSMasami Hiramatsu 23614a8fd7cSMasami Hiramatsu /* A file path -- this is an offline module */ 23714a8fd7cSMasami Hiramatsu if (module && strchr(module, '/')) 23814a8fd7cSMasami Hiramatsu path = module; 23914a8fd7cSMasami Hiramatsu else { 24014a8fd7cSMasami Hiramatsu path = kernel_get_module_path(module); 241ff741783SMasami Hiramatsu 242469b9b88SMasami Hiramatsu if (!path) { 2430e43e5d2SMasami Hiramatsu pr_err("Failed to find path of %s module.\n", 2440e43e5d2SMasami Hiramatsu module ?: "kernel"); 245ff741783SMasami Hiramatsu return NULL; 246469b9b88SMasami Hiramatsu } 24714a8fd7cSMasami Hiramatsu } 248ff741783SMasami Hiramatsu return debuginfo__new(path); 249e0faa8d3SMasami Hiramatsu } 2504b4da7f7SMasami Hiramatsu 2510e60836bSSrikar Dronamraju /* 2520e60836bSSrikar Dronamraju * Convert trace point to probe point with debuginfo 2530e60836bSSrikar Dronamraju * Currently only handles kprobes. 2540e60836bSSrikar Dronamraju */ 2550e60836bSSrikar Dronamraju static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 2564b4da7f7SMasami Hiramatsu struct perf_probe_point *pp) 2574b4da7f7SMasami Hiramatsu { 2584b4da7f7SMasami Hiramatsu struct symbol *sym; 259469b9b88SMasami Hiramatsu struct map *map; 260469b9b88SMasami Hiramatsu u64 addr; 261469b9b88SMasami Hiramatsu int ret = -ENOENT; 262ff741783SMasami Hiramatsu struct debuginfo *dinfo; 2634b4da7f7SMasami Hiramatsu 264469b9b88SMasami Hiramatsu sym = __find_kernel_function_by_name(tp->symbol, &map); 2654b4da7f7SMasami Hiramatsu if (sym) { 266469b9b88SMasami Hiramatsu addr = map->unmap_ip(map, sym->start + tp->offset); 2679486aa38SArnaldo Carvalho de Melo pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol, 268469b9b88SMasami Hiramatsu tp->offset, addr); 269ff741783SMasami Hiramatsu 270ff741783SMasami Hiramatsu dinfo = debuginfo__new_online_kernel(addr); 271ff741783SMasami Hiramatsu if (dinfo) { 272ff741783SMasami Hiramatsu ret = debuginfo__find_probe_point(dinfo, 273ff741783SMasami Hiramatsu (unsigned long)addr, pp); 274ff741783SMasami Hiramatsu debuginfo__delete(dinfo); 275ff741783SMasami Hiramatsu } else { 276ff741783SMasami Hiramatsu pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n", 277ff741783SMasami Hiramatsu addr); 278ff741783SMasami Hiramatsu ret = -ENOENT; 279ff741783SMasami Hiramatsu } 280146a1439SMasami Hiramatsu } 2814b4da7f7SMasami Hiramatsu if (ret <= 0) { 282146a1439SMasami Hiramatsu pr_debug("Failed to find corresponding probes from " 283146a1439SMasami Hiramatsu "debuginfo. Use kprobe event information.\n"); 284225466f1SSrikar Dronamraju return convert_to_perf_probe_point(tp, pp); 2854b4da7f7SMasami Hiramatsu } 2864b4da7f7SMasami Hiramatsu pp->retprobe = tp->retprobe; 287146a1439SMasami Hiramatsu 288146a1439SMasami Hiramatsu return 0; 2894b4da7f7SMasami Hiramatsu } 2904b4da7f7SMasami Hiramatsu 29199ca4233SMasami Hiramatsu static int get_text_start_address(const char *exec, unsigned long *address) 29299ca4233SMasami Hiramatsu { 29399ca4233SMasami Hiramatsu Elf *elf; 29499ca4233SMasami Hiramatsu GElf_Ehdr ehdr; 29599ca4233SMasami Hiramatsu GElf_Shdr shdr; 29699ca4233SMasami Hiramatsu int fd, ret = -ENOENT; 29799ca4233SMasami Hiramatsu 29899ca4233SMasami Hiramatsu fd = open(exec, O_RDONLY); 29999ca4233SMasami Hiramatsu if (fd < 0) 30099ca4233SMasami Hiramatsu return -errno; 30199ca4233SMasami Hiramatsu 30299ca4233SMasami Hiramatsu elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 30399ca4233SMasami Hiramatsu if (elf == NULL) 30499ca4233SMasami Hiramatsu return -EINVAL; 30599ca4233SMasami Hiramatsu 30699ca4233SMasami Hiramatsu if (gelf_getehdr(elf, &ehdr) == NULL) 30799ca4233SMasami Hiramatsu goto out; 30899ca4233SMasami Hiramatsu 30999ca4233SMasami Hiramatsu if (!elf_section_by_name(elf, &ehdr, &shdr, ".text", NULL)) 31099ca4233SMasami Hiramatsu goto out; 31199ca4233SMasami Hiramatsu 31299ca4233SMasami Hiramatsu *address = shdr.sh_addr - shdr.sh_offset; 31399ca4233SMasami Hiramatsu ret = 0; 31499ca4233SMasami Hiramatsu out: 31599ca4233SMasami Hiramatsu elf_end(elf); 31699ca4233SMasami Hiramatsu return ret; 31799ca4233SMasami Hiramatsu } 31899ca4233SMasami Hiramatsu 319fb7345bbSMasami Hiramatsu static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, 320fb7345bbSMasami Hiramatsu int ntevs, const char *exec) 321fb7345bbSMasami Hiramatsu { 322fb7345bbSMasami Hiramatsu int i, ret = 0; 323fb7345bbSMasami Hiramatsu unsigned long offset, stext = 0; 324fb7345bbSMasami Hiramatsu char buf[32]; 325fb7345bbSMasami Hiramatsu 326fb7345bbSMasami Hiramatsu if (!exec) 327fb7345bbSMasami Hiramatsu return 0; 328fb7345bbSMasami Hiramatsu 329fb7345bbSMasami Hiramatsu ret = get_text_start_address(exec, &stext); 330fb7345bbSMasami Hiramatsu if (ret < 0) 331fb7345bbSMasami Hiramatsu return ret; 332fb7345bbSMasami Hiramatsu 333fb7345bbSMasami Hiramatsu for (i = 0; i < ntevs && ret >= 0; i++) { 334981a2379SMasami Hiramatsu /* point.address is the addres of point.symbol + point.offset */ 335fb7345bbSMasami Hiramatsu offset = tevs[i].point.address - stext; 336fb7345bbSMasami Hiramatsu tevs[i].point.offset = 0; 33774cf249dSArnaldo Carvalho de Melo zfree(&tevs[i].point.symbol); 338fb7345bbSMasami Hiramatsu ret = e_snprintf(buf, 32, "0x%lx", offset); 339fb7345bbSMasami Hiramatsu if (ret < 0) 340fb7345bbSMasami Hiramatsu break; 341fb7345bbSMasami Hiramatsu tevs[i].point.module = strdup(exec); 342fb7345bbSMasami Hiramatsu tevs[i].point.symbol = strdup(buf); 343fb7345bbSMasami Hiramatsu if (!tevs[i].point.symbol || !tevs[i].point.module) { 344fb7345bbSMasami Hiramatsu ret = -ENOMEM; 345fb7345bbSMasami Hiramatsu break; 346fb7345bbSMasami Hiramatsu } 347fb7345bbSMasami Hiramatsu tevs[i].uprobes = true; 348fb7345bbSMasami Hiramatsu } 349fb7345bbSMasami Hiramatsu 350fb7345bbSMasami Hiramatsu return ret; 351fb7345bbSMasami Hiramatsu } 352fb7345bbSMasami Hiramatsu 353190b57fcSMasami Hiramatsu static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, 354190b57fcSMasami Hiramatsu int ntevs, const char *module) 355190b57fcSMasami Hiramatsu { 35614a8fd7cSMasami Hiramatsu int i, ret = 0; 35714a8fd7cSMasami Hiramatsu char *tmp; 35814a8fd7cSMasami Hiramatsu 35914a8fd7cSMasami Hiramatsu if (!module) 36014a8fd7cSMasami Hiramatsu return 0; 36114a8fd7cSMasami Hiramatsu 36214a8fd7cSMasami Hiramatsu tmp = strrchr(module, '/'); 36314a8fd7cSMasami Hiramatsu if (tmp) { 36414a8fd7cSMasami Hiramatsu /* This is a module path -- get the module name */ 36514a8fd7cSMasami Hiramatsu module = strdup(tmp + 1); 36614a8fd7cSMasami Hiramatsu if (!module) 36714a8fd7cSMasami Hiramatsu return -ENOMEM; 36814a8fd7cSMasami Hiramatsu tmp = strchr(module, '.'); 36914a8fd7cSMasami Hiramatsu if (tmp) 37014a8fd7cSMasami Hiramatsu *tmp = '\0'; 37114a8fd7cSMasami Hiramatsu tmp = (char *)module; /* For free() */ 37214a8fd7cSMasami Hiramatsu } 37314a8fd7cSMasami Hiramatsu 374190b57fcSMasami Hiramatsu for (i = 0; i < ntevs; i++) { 375190b57fcSMasami Hiramatsu tevs[i].point.module = strdup(module); 37614a8fd7cSMasami Hiramatsu if (!tevs[i].point.module) { 37714a8fd7cSMasami Hiramatsu ret = -ENOMEM; 37814a8fd7cSMasami Hiramatsu break; 379190b57fcSMasami Hiramatsu } 38014a8fd7cSMasami Hiramatsu } 38114a8fd7cSMasami Hiramatsu 38214a8fd7cSMasami Hiramatsu free(tmp); 38314a8fd7cSMasami Hiramatsu return ret; 384190b57fcSMasami Hiramatsu } 385190b57fcSMasami Hiramatsu 386981d05adSMasami Hiramatsu static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs) 387981d05adSMasami Hiramatsu { 388981d05adSMasami Hiramatsu int i; 389981d05adSMasami Hiramatsu 390981d05adSMasami Hiramatsu for (i = 0; i < ntevs; i++) 391981d05adSMasami Hiramatsu clear_probe_trace_event(tevs + i); 392981d05adSMasami Hiramatsu } 393981d05adSMasami Hiramatsu 3944b4da7f7SMasami Hiramatsu /* Try to find perf_probe_event with debuginfo */ 3950e60836bSSrikar Dronamraju static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 3960e60836bSSrikar Dronamraju struct probe_trace_event **tevs, 3974eced234SSrikar Dronamraju int max_tevs, const char *target) 3984b4da7f7SMasami Hiramatsu { 3994b4da7f7SMasami Hiramatsu bool need_dwarf = perf_probe_event_need_dwarf(pev); 400225466f1SSrikar Dronamraju struct debuginfo *dinfo; 401190b57fcSMasami Hiramatsu int ntevs, ret = 0; 4024b4da7f7SMasami Hiramatsu 403225466f1SSrikar Dronamraju dinfo = open_debuginfo(target); 404225466f1SSrikar Dronamraju 405ff741783SMasami Hiramatsu if (!dinfo) { 406146a1439SMasami Hiramatsu if (need_dwarf) { 407146a1439SMasami Hiramatsu pr_warning("Failed to open debuginfo file.\n"); 408ff741783SMasami Hiramatsu return -ENOENT; 409146a1439SMasami Hiramatsu } 410ff741783SMasami Hiramatsu pr_debug("Could not open debuginfo. Try to use symbols.\n"); 4114b4da7f7SMasami Hiramatsu return 0; 4124b4da7f7SMasami Hiramatsu } 4134b4da7f7SMasami Hiramatsu 414ff741783SMasami Hiramatsu /* Searching trace events corresponding to a probe event */ 415ff741783SMasami Hiramatsu ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs); 416ff741783SMasami Hiramatsu 417ff741783SMasami Hiramatsu debuginfo__delete(dinfo); 4184b4da7f7SMasami Hiramatsu 419146a1439SMasami Hiramatsu if (ntevs > 0) { /* Succeeded to find trace events */ 4200e60836bSSrikar Dronamraju pr_debug("find %d probe_trace_events.\n", ntevs); 421fb7345bbSMasami Hiramatsu if (target) { 422fb7345bbSMasami Hiramatsu if (pev->uprobes) 423fb7345bbSMasami Hiramatsu ret = add_exec_to_probe_trace_events(*tevs, 424fb7345bbSMasami Hiramatsu ntevs, target); 425fb7345bbSMasami Hiramatsu else 426fb7345bbSMasami Hiramatsu ret = add_module_to_probe_trace_events(*tevs, 427fb7345bbSMasami Hiramatsu ntevs, target); 428fb7345bbSMasami Hiramatsu } 429981d05adSMasami Hiramatsu if (ret < 0) { 430981d05adSMasami Hiramatsu clear_probe_trace_events(*tevs, ntevs); 431981d05adSMasami Hiramatsu zfree(tevs); 432981d05adSMasami Hiramatsu } 433190b57fcSMasami Hiramatsu return ret < 0 ? ret : ntevs; 434146a1439SMasami Hiramatsu } 4354b4da7f7SMasami Hiramatsu 436146a1439SMasami Hiramatsu if (ntevs == 0) { /* No error but failed to find probe point. */ 437146a1439SMasami Hiramatsu pr_warning("Probe point '%s' not found.\n", 4384b4da7f7SMasami Hiramatsu synthesize_perf_probe_point(&pev->point)); 439146a1439SMasami Hiramatsu return -ENOENT; 440146a1439SMasami Hiramatsu } 441146a1439SMasami Hiramatsu /* Error path : ntevs < 0 */ 44215eca306SMasami Hiramatsu pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); 44315eca306SMasami Hiramatsu if (ntevs == -EBADF) { 44415eca306SMasami Hiramatsu pr_warning("Warning: No dwarf info found in the vmlinux - " 44515eca306SMasami Hiramatsu "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); 44615eca306SMasami Hiramatsu if (!need_dwarf) { 4470e43e5d2SMasami Hiramatsu pr_debug("Trying to use symbols.\n"); 4484b4da7f7SMasami Hiramatsu return 0; 4494b4da7f7SMasami Hiramatsu } 45015eca306SMasami Hiramatsu } 45115eca306SMasami Hiramatsu return ntevs; 45215eca306SMasami Hiramatsu } 4534b4da7f7SMasami Hiramatsu 4547cf0b79eSMasami Hiramatsu /* 4557cf0b79eSMasami Hiramatsu * Find a src file from a DWARF tag path. Prepend optional source path prefix 4567cf0b79eSMasami Hiramatsu * and chop off leading directories that do not exist. Result is passed back as 4577cf0b79eSMasami Hiramatsu * a newly allocated path on success. 4587cf0b79eSMasami Hiramatsu * Return 0 if file was found and readable, -errno otherwise. 4597cf0b79eSMasami Hiramatsu */ 4606a330a3cSMasami Hiramatsu static int get_real_path(const char *raw_path, const char *comp_dir, 4616a330a3cSMasami Hiramatsu char **new_path) 4627cf0b79eSMasami Hiramatsu { 4636a330a3cSMasami Hiramatsu const char *prefix = symbol_conf.source_prefix; 4646a330a3cSMasami Hiramatsu 4656a330a3cSMasami Hiramatsu if (!prefix) { 4666a330a3cSMasami Hiramatsu if (raw_path[0] != '/' && comp_dir) 4676a330a3cSMasami Hiramatsu /* If not an absolute path, try to use comp_dir */ 4686a330a3cSMasami Hiramatsu prefix = comp_dir; 4696a330a3cSMasami Hiramatsu else { 4707cf0b79eSMasami Hiramatsu if (access(raw_path, R_OK) == 0) { 4717cf0b79eSMasami Hiramatsu *new_path = strdup(raw_path); 4727cf0b79eSMasami Hiramatsu return 0; 4737cf0b79eSMasami Hiramatsu } else 4747cf0b79eSMasami Hiramatsu return -errno; 4757cf0b79eSMasami Hiramatsu } 4766a330a3cSMasami Hiramatsu } 4777cf0b79eSMasami Hiramatsu 4786a330a3cSMasami Hiramatsu *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2)); 4797cf0b79eSMasami Hiramatsu if (!*new_path) 4807cf0b79eSMasami Hiramatsu return -ENOMEM; 4817cf0b79eSMasami Hiramatsu 4827cf0b79eSMasami Hiramatsu for (;;) { 4836a330a3cSMasami Hiramatsu sprintf(*new_path, "%s/%s", prefix, raw_path); 4847cf0b79eSMasami Hiramatsu 4857cf0b79eSMasami Hiramatsu if (access(*new_path, R_OK) == 0) 4867cf0b79eSMasami Hiramatsu return 0; 4877cf0b79eSMasami Hiramatsu 4886a330a3cSMasami Hiramatsu if (!symbol_conf.source_prefix) 4896a330a3cSMasami Hiramatsu /* In case of searching comp_dir, don't retry */ 4906a330a3cSMasami Hiramatsu return -errno; 4916a330a3cSMasami Hiramatsu 4927cf0b79eSMasami Hiramatsu switch (errno) { 4937cf0b79eSMasami Hiramatsu case ENAMETOOLONG: 4947cf0b79eSMasami Hiramatsu case ENOENT: 4957cf0b79eSMasami Hiramatsu case EROFS: 4967cf0b79eSMasami Hiramatsu case EFAULT: 4977cf0b79eSMasami Hiramatsu raw_path = strchr(++raw_path, '/'); 4987cf0b79eSMasami Hiramatsu if (!raw_path) { 49904662523SArnaldo Carvalho de Melo zfree(new_path); 5007cf0b79eSMasami Hiramatsu return -ENOENT; 5017cf0b79eSMasami Hiramatsu } 5027cf0b79eSMasami Hiramatsu continue; 5037cf0b79eSMasami Hiramatsu 5047cf0b79eSMasami Hiramatsu default: 50504662523SArnaldo Carvalho de Melo zfree(new_path); 5067cf0b79eSMasami Hiramatsu return -errno; 5077cf0b79eSMasami Hiramatsu } 5087cf0b79eSMasami Hiramatsu } 5097cf0b79eSMasami Hiramatsu } 5107cf0b79eSMasami Hiramatsu 5114b4da7f7SMasami Hiramatsu #define LINEBUF_SIZE 256 5124b4da7f7SMasami Hiramatsu #define NR_ADDITIONAL_LINES 2 5134b4da7f7SMasami Hiramatsu 514fde52dbdSFranck Bui-Huu static int __show_one_line(FILE *fp, int l, bool skip, bool show_num) 5154b4da7f7SMasami Hiramatsu { 5164b4da7f7SMasami Hiramatsu char buf[LINEBUF_SIZE]; 517befe3414SFranck Bui-Huu const char *color = show_num ? "" : PERF_COLOR_BLUE; 518befe3414SFranck Bui-Huu const char *prefix = NULL; 5194b4da7f7SMasami Hiramatsu 520befe3414SFranck Bui-Huu do { 5214b4da7f7SMasami Hiramatsu if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 5224b4da7f7SMasami Hiramatsu goto error; 523befe3414SFranck Bui-Huu if (skip) 524befe3414SFranck Bui-Huu continue; 525befe3414SFranck Bui-Huu if (!prefix) { 526befe3414SFranck Bui-Huu prefix = show_num ? "%7d " : " "; 527befe3414SFranck Bui-Huu color_fprintf(stdout, color, prefix, l); 5284b4da7f7SMasami Hiramatsu } 529befe3414SFranck Bui-Huu color_fprintf(stdout, color, "%s", buf); 5304b4da7f7SMasami Hiramatsu 531befe3414SFranck Bui-Huu } while (strchr(buf, '\n') == NULL); 532146a1439SMasami Hiramatsu 533fde52dbdSFranck Bui-Huu return 1; 5344b4da7f7SMasami Hiramatsu error: 535fde52dbdSFranck Bui-Huu if (ferror(fp)) { 53632b2b6ecSFranck Bui-Huu pr_warning("File read error: %s\n", strerror(errno)); 537146a1439SMasami Hiramatsu return -1; 5384b4da7f7SMasami Hiramatsu } 539fde52dbdSFranck Bui-Huu return 0; 540fde52dbdSFranck Bui-Huu } 541fde52dbdSFranck Bui-Huu 542fde52dbdSFranck Bui-Huu static int _show_one_line(FILE *fp, int l, bool skip, bool show_num) 543fde52dbdSFranck Bui-Huu { 544fde52dbdSFranck Bui-Huu int rv = __show_one_line(fp, l, skip, show_num); 545fde52dbdSFranck Bui-Huu if (rv == 0) { 546fde52dbdSFranck Bui-Huu pr_warning("Source file is shorter than expected.\n"); 547fde52dbdSFranck Bui-Huu rv = -1; 548fde52dbdSFranck Bui-Huu } 549fde52dbdSFranck Bui-Huu return rv; 550fde52dbdSFranck Bui-Huu } 551fde52dbdSFranck Bui-Huu 552fde52dbdSFranck Bui-Huu #define show_one_line_with_num(f,l) _show_one_line(f,l,false,true) 553fde52dbdSFranck Bui-Huu #define show_one_line(f,l) _show_one_line(f,l,false,false) 554fde52dbdSFranck Bui-Huu #define skip_one_line(f,l) _show_one_line(f,l,true,false) 555fde52dbdSFranck Bui-Huu #define show_one_line_or_eof(f,l) __show_one_line(f,l,false,false) 5564b4da7f7SMasami Hiramatsu 5574b4da7f7SMasami Hiramatsu /* 5584b4da7f7SMasami Hiramatsu * Show line-range always requires debuginfo to find source file and 5594b4da7f7SMasami Hiramatsu * line number. 5604b4da7f7SMasami Hiramatsu */ 561*ee45b6c2SMasami Hiramatsu static int __show_line_range(struct line_range *lr, const char *module) 5624b4da7f7SMasami Hiramatsu { 563d3b63d7aSMasami Hiramatsu int l = 1; 5644b4da7f7SMasami Hiramatsu struct line_node *ln; 565ff741783SMasami Hiramatsu struct debuginfo *dinfo; 5664b4da7f7SMasami Hiramatsu FILE *fp; 567ff741783SMasami Hiramatsu int ret; 5687cf0b79eSMasami Hiramatsu char *tmp; 5694b4da7f7SMasami Hiramatsu 5704b4da7f7SMasami Hiramatsu /* Search a line range */ 571ff741783SMasami Hiramatsu dinfo = open_debuginfo(module); 572ff741783SMasami Hiramatsu if (!dinfo) { 573146a1439SMasami Hiramatsu pr_warning("Failed to open debuginfo file.\n"); 574ff741783SMasami Hiramatsu return -ENOENT; 575146a1439SMasami Hiramatsu } 576146a1439SMasami Hiramatsu 577ff741783SMasami Hiramatsu ret = debuginfo__find_line_range(dinfo, lr); 578ff741783SMasami Hiramatsu debuginfo__delete(dinfo); 579146a1439SMasami Hiramatsu if (ret == 0) { 580146a1439SMasami Hiramatsu pr_warning("Specified source line is not found.\n"); 581146a1439SMasami Hiramatsu return -ENOENT; 582146a1439SMasami Hiramatsu } else if (ret < 0) { 583146a1439SMasami Hiramatsu pr_warning("Debuginfo analysis failed. (%d)\n", ret); 584146a1439SMasami Hiramatsu return ret; 585146a1439SMasami Hiramatsu } 5864b4da7f7SMasami Hiramatsu 5877cf0b79eSMasami Hiramatsu /* Convert source file path */ 5887cf0b79eSMasami Hiramatsu tmp = lr->path; 5896a330a3cSMasami Hiramatsu ret = get_real_path(tmp, lr->comp_dir, &lr->path); 5907cf0b79eSMasami Hiramatsu free(tmp); /* Free old path */ 5917cf0b79eSMasami Hiramatsu if (ret < 0) { 5927cf0b79eSMasami Hiramatsu pr_warning("Failed to find source file. (%d)\n", ret); 5937cf0b79eSMasami Hiramatsu return ret; 5947cf0b79eSMasami Hiramatsu } 5957cf0b79eSMasami Hiramatsu 5964b4da7f7SMasami Hiramatsu setup_pager(); 5974b4da7f7SMasami Hiramatsu 5984b4da7f7SMasami Hiramatsu if (lr->function) 5998737ebdeSMasami Hiramatsu fprintf(stdout, "<%s@%s:%d>\n", lr->function, lr->path, 6004b4da7f7SMasami Hiramatsu lr->start - lr->offset); 6014b4da7f7SMasami Hiramatsu else 60262c15fc4SFranck Bui-Huu fprintf(stdout, "<%s:%d>\n", lr->path, lr->start); 6034b4da7f7SMasami Hiramatsu 6044b4da7f7SMasami Hiramatsu fp = fopen(lr->path, "r"); 605146a1439SMasami Hiramatsu if (fp == NULL) { 606146a1439SMasami Hiramatsu pr_warning("Failed to open %s: %s\n", lr->path, 607146a1439SMasami Hiramatsu strerror(errno)); 608146a1439SMasami Hiramatsu return -errno; 609146a1439SMasami Hiramatsu } 6104b4da7f7SMasami Hiramatsu /* Skip to starting line number */ 61144b81e92SFranck Bui-Huu while (l < lr->start) { 612fde52dbdSFranck Bui-Huu ret = skip_one_line(fp, l++); 613146a1439SMasami Hiramatsu if (ret < 0) 614146a1439SMasami Hiramatsu goto end; 61544b81e92SFranck Bui-Huu } 6164b4da7f7SMasami Hiramatsu 6174b4da7f7SMasami Hiramatsu list_for_each_entry(ln, &lr->line_list, list) { 61844b81e92SFranck Bui-Huu for (; ln->line > l; l++) { 619fde52dbdSFranck Bui-Huu ret = show_one_line(fp, l - lr->offset); 62044b81e92SFranck Bui-Huu if (ret < 0) 62144b81e92SFranck Bui-Huu goto end; 62244b81e92SFranck Bui-Huu } 623fde52dbdSFranck Bui-Huu ret = show_one_line_with_num(fp, l++ - lr->offset); 624146a1439SMasami Hiramatsu if (ret < 0) 625146a1439SMasami Hiramatsu goto end; 6264b4da7f7SMasami Hiramatsu } 6274b4da7f7SMasami Hiramatsu 6284b4da7f7SMasami Hiramatsu if (lr->end == INT_MAX) 6294b4da7f7SMasami Hiramatsu lr->end = l + NR_ADDITIONAL_LINES; 630fde52dbdSFranck Bui-Huu while (l <= lr->end) { 631fde52dbdSFranck Bui-Huu ret = show_one_line_or_eof(fp, l++ - lr->offset); 632fde52dbdSFranck Bui-Huu if (ret <= 0) 63344b81e92SFranck Bui-Huu break; 63444b81e92SFranck Bui-Huu } 635146a1439SMasami Hiramatsu end: 6364b4da7f7SMasami Hiramatsu fclose(fp); 637146a1439SMasami Hiramatsu return ret; 6384b4da7f7SMasami Hiramatsu } 6394b4da7f7SMasami Hiramatsu 640*ee45b6c2SMasami Hiramatsu int show_line_range(struct line_range *lr, const char *module) 641*ee45b6c2SMasami Hiramatsu { 642*ee45b6c2SMasami Hiramatsu int ret; 643*ee45b6c2SMasami Hiramatsu 644*ee45b6c2SMasami Hiramatsu ret = init_symbol_maps(false); 645*ee45b6c2SMasami Hiramatsu if (ret < 0) 646*ee45b6c2SMasami Hiramatsu return ret; 647*ee45b6c2SMasami Hiramatsu ret = __show_line_range(lr, module); 648*ee45b6c2SMasami Hiramatsu exit_symbol_maps(); 649*ee45b6c2SMasami Hiramatsu 650*ee45b6c2SMasami Hiramatsu return ret; 651*ee45b6c2SMasami Hiramatsu } 652*ee45b6c2SMasami Hiramatsu 653ff741783SMasami Hiramatsu static int show_available_vars_at(struct debuginfo *dinfo, 654ff741783SMasami Hiramatsu struct perf_probe_event *pev, 655bd09d7b5SMasami Hiramatsu int max_vls, struct strfilter *_filter, 656bd09d7b5SMasami Hiramatsu bool externs) 657cf6eb489SMasami Hiramatsu { 658cf6eb489SMasami Hiramatsu char *buf; 659bd09d7b5SMasami Hiramatsu int ret, i, nvars; 660cf6eb489SMasami Hiramatsu struct str_node *node; 661cf6eb489SMasami Hiramatsu struct variable_list *vls = NULL, *vl; 662bd09d7b5SMasami Hiramatsu const char *var; 663cf6eb489SMasami Hiramatsu 664cf6eb489SMasami Hiramatsu buf = synthesize_perf_probe_point(&pev->point); 665cf6eb489SMasami Hiramatsu if (!buf) 666cf6eb489SMasami Hiramatsu return -EINVAL; 667cf6eb489SMasami Hiramatsu pr_debug("Searching variables at %s\n", buf); 668cf6eb489SMasami Hiramatsu 669ff741783SMasami Hiramatsu ret = debuginfo__find_available_vars_at(dinfo, pev, &vls, 670ff741783SMasami Hiramatsu max_vls, externs); 671bd09d7b5SMasami Hiramatsu if (ret <= 0) { 672bd09d7b5SMasami Hiramatsu pr_err("Failed to find variables at %s (%d)\n", buf, ret); 673bd09d7b5SMasami Hiramatsu goto end; 674bd09d7b5SMasami Hiramatsu } 675bd09d7b5SMasami Hiramatsu /* Some variables are found */ 676cf6eb489SMasami Hiramatsu fprintf(stdout, "Available variables at %s\n", buf); 677cf6eb489SMasami Hiramatsu for (i = 0; i < ret; i++) { 678cf6eb489SMasami Hiramatsu vl = &vls[i]; 679cf6eb489SMasami Hiramatsu /* 680cf6eb489SMasami Hiramatsu * A probe point might be converted to 681cf6eb489SMasami Hiramatsu * several trace points. 682cf6eb489SMasami Hiramatsu */ 683cf6eb489SMasami Hiramatsu fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, 684cf6eb489SMasami Hiramatsu vl->point.offset); 68574cf249dSArnaldo Carvalho de Melo zfree(&vl->point.symbol); 686bd09d7b5SMasami Hiramatsu nvars = 0; 687cf6eb489SMasami Hiramatsu if (vl->vars) { 688bd09d7b5SMasami Hiramatsu strlist__for_each(node, vl->vars) { 689bd09d7b5SMasami Hiramatsu var = strchr(node->s, '\t') + 1; 690bd09d7b5SMasami Hiramatsu if (strfilter__compare(_filter, var)) { 691cf6eb489SMasami Hiramatsu fprintf(stdout, "\t\t%s\n", node->s); 692bd09d7b5SMasami Hiramatsu nvars++; 693bd09d7b5SMasami Hiramatsu } 694bd09d7b5SMasami Hiramatsu } 695cf6eb489SMasami Hiramatsu strlist__delete(vl->vars); 696bd09d7b5SMasami Hiramatsu } 697bd09d7b5SMasami Hiramatsu if (nvars == 0) 698bd09d7b5SMasami Hiramatsu fprintf(stdout, "\t\t(No matched variables)\n"); 699cf6eb489SMasami Hiramatsu } 700cf6eb489SMasami Hiramatsu free(vls); 701bd09d7b5SMasami Hiramatsu end: 702cf6eb489SMasami Hiramatsu free(buf); 703cf6eb489SMasami Hiramatsu return ret; 704cf6eb489SMasami Hiramatsu } 705cf6eb489SMasami Hiramatsu 706cf6eb489SMasami Hiramatsu /* Show available variables on given probe point */ 707cf6eb489SMasami Hiramatsu int show_available_vars(struct perf_probe_event *pevs, int npevs, 708bd09d7b5SMasami Hiramatsu int max_vls, const char *module, 709bd09d7b5SMasami Hiramatsu struct strfilter *_filter, bool externs) 710cf6eb489SMasami Hiramatsu { 711ff741783SMasami Hiramatsu int i, ret = 0; 712ff741783SMasami Hiramatsu struct debuginfo *dinfo; 713cf6eb489SMasami Hiramatsu 714*ee45b6c2SMasami Hiramatsu ret = init_symbol_maps(false); 715cf6eb489SMasami Hiramatsu if (ret < 0) 716cf6eb489SMasami Hiramatsu return ret; 717cf6eb489SMasami Hiramatsu 718ff741783SMasami Hiramatsu dinfo = open_debuginfo(module); 719ff741783SMasami Hiramatsu if (!dinfo) { 720ff741783SMasami Hiramatsu pr_warning("Failed to open debuginfo file.\n"); 721*ee45b6c2SMasami Hiramatsu ret = -ENOENT; 722*ee45b6c2SMasami Hiramatsu goto out; 723ff741783SMasami Hiramatsu } 724ff741783SMasami Hiramatsu 725cc446446SMasami Hiramatsu setup_pager(); 726cc446446SMasami Hiramatsu 727ff741783SMasami Hiramatsu for (i = 0; i < npevs && ret >= 0; i++) 728ff741783SMasami Hiramatsu ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter, 729bd09d7b5SMasami Hiramatsu externs); 730ff741783SMasami Hiramatsu 731ff741783SMasami Hiramatsu debuginfo__delete(dinfo); 732*ee45b6c2SMasami Hiramatsu out: 733*ee45b6c2SMasami Hiramatsu exit_symbol_maps(); 734cf6eb489SMasami Hiramatsu return ret; 735cf6eb489SMasami Hiramatsu } 736cf6eb489SMasami Hiramatsu 73789fe808aSIngo Molnar #else /* !HAVE_DWARF_SUPPORT */ 7384b4da7f7SMasami Hiramatsu 7390e60836bSSrikar Dronamraju static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 7404b4da7f7SMasami Hiramatsu struct perf_probe_point *pp) 7414b4da7f7SMasami Hiramatsu { 742469b9b88SMasami Hiramatsu struct symbol *sym; 743469b9b88SMasami Hiramatsu 744469b9b88SMasami Hiramatsu sym = __find_kernel_function_by_name(tp->symbol, NULL); 745469b9b88SMasami Hiramatsu if (!sym) { 746469b9b88SMasami Hiramatsu pr_err("Failed to find symbol %s in kernel.\n", tp->symbol); 747469b9b88SMasami Hiramatsu return -ENOENT; 748469b9b88SMasami Hiramatsu } 749146a1439SMasami Hiramatsu 750225466f1SSrikar Dronamraju return convert_to_perf_probe_point(tp, pp); 7514b4da7f7SMasami Hiramatsu } 7524b4da7f7SMasami Hiramatsu 7530e60836bSSrikar Dronamraju static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 7541d037ca1SIrina Tirdea struct probe_trace_event **tevs __maybe_unused, 7551d027ee9SArnaldo Carvalho de Melo int max_tevs __maybe_unused, 7561d027ee9SArnaldo Carvalho de Melo const char *target __maybe_unused) 7574b4da7f7SMasami Hiramatsu { 758146a1439SMasami Hiramatsu if (perf_probe_event_need_dwarf(pev)) { 759146a1439SMasami Hiramatsu pr_warning("Debuginfo-analysis is not supported.\n"); 760146a1439SMasami Hiramatsu return -ENOSYS; 761146a1439SMasami Hiramatsu } 762225466f1SSrikar Dronamraju 7634b4da7f7SMasami Hiramatsu return 0; 7644b4da7f7SMasami Hiramatsu } 7654b4da7f7SMasami Hiramatsu 7661d037ca1SIrina Tirdea int show_line_range(struct line_range *lr __maybe_unused, 7671d037ca1SIrina Tirdea const char *module __maybe_unused) 7684b4da7f7SMasami Hiramatsu { 769146a1439SMasami Hiramatsu pr_warning("Debuginfo-analysis is not supported.\n"); 770146a1439SMasami Hiramatsu return -ENOSYS; 7714b4da7f7SMasami Hiramatsu } 7724b4da7f7SMasami Hiramatsu 7731d037ca1SIrina Tirdea int show_available_vars(struct perf_probe_event *pevs __maybe_unused, 7741d037ca1SIrina Tirdea int npevs __maybe_unused, int max_vls __maybe_unused, 7751d037ca1SIrina Tirdea const char *module __maybe_unused, 7761d037ca1SIrina Tirdea struct strfilter *filter __maybe_unused, 7771d037ca1SIrina Tirdea bool externs __maybe_unused) 778cf6eb489SMasami Hiramatsu { 779cf6eb489SMasami Hiramatsu pr_warning("Debuginfo-analysis is not supported.\n"); 780cf6eb489SMasami Hiramatsu return -ENOSYS; 781cf6eb489SMasami Hiramatsu } 782e0faa8d3SMasami Hiramatsu #endif 783e0faa8d3SMasami Hiramatsu 784e53b00d3SMasami Hiramatsu void line_range__clear(struct line_range *lr) 785e53b00d3SMasami Hiramatsu { 786e53b00d3SMasami Hiramatsu struct line_node *ln; 787e53b00d3SMasami Hiramatsu 788e53b00d3SMasami Hiramatsu free(lr->function); 789e53b00d3SMasami Hiramatsu free(lr->file); 790e53b00d3SMasami Hiramatsu free(lr->path); 791e53b00d3SMasami Hiramatsu free(lr->comp_dir); 792e53b00d3SMasami Hiramatsu while (!list_empty(&lr->line_list)) { 793e53b00d3SMasami Hiramatsu ln = list_first_entry(&lr->line_list, struct line_node, list); 794e53b00d3SMasami Hiramatsu list_del(&ln->list); 795e53b00d3SMasami Hiramatsu free(ln); 796e53b00d3SMasami Hiramatsu } 797e53b00d3SMasami Hiramatsu memset(lr, 0, sizeof(*lr)); 798e53b00d3SMasami Hiramatsu } 799e53b00d3SMasami Hiramatsu 800e53b00d3SMasami Hiramatsu void line_range__init(struct line_range *lr) 801e53b00d3SMasami Hiramatsu { 802e53b00d3SMasami Hiramatsu memset(lr, 0, sizeof(*lr)); 803e53b00d3SMasami Hiramatsu INIT_LIST_HEAD(&lr->line_list); 804e53b00d3SMasami Hiramatsu } 805e53b00d3SMasami Hiramatsu 80621dd9ae5SFranck Bui-Huu static int parse_line_num(char **ptr, int *val, const char *what) 80721dd9ae5SFranck Bui-Huu { 80821dd9ae5SFranck Bui-Huu const char *start = *ptr; 80921dd9ae5SFranck Bui-Huu 81021dd9ae5SFranck Bui-Huu errno = 0; 81121dd9ae5SFranck Bui-Huu *val = strtol(*ptr, ptr, 0); 81221dd9ae5SFranck Bui-Huu if (errno || *ptr == start) { 81321dd9ae5SFranck Bui-Huu semantic_error("'%s' is not a valid number.\n", what); 81421dd9ae5SFranck Bui-Huu return -EINVAL; 81521dd9ae5SFranck Bui-Huu } 81621dd9ae5SFranck Bui-Huu return 0; 81721dd9ae5SFranck Bui-Huu } 81821dd9ae5SFranck Bui-Huu 8199d95b580SFranck Bui-Huu /* 8209d95b580SFranck Bui-Huu * Stuff 'lr' according to the line range described by 'arg'. 8219d95b580SFranck Bui-Huu * The line range syntax is described by: 8229d95b580SFranck Bui-Huu * 8239d95b580SFranck Bui-Huu * SRC[:SLN[+NUM|-ELN]] 824e116dfa1SMasami Hiramatsu * FNC[@SRC][:SLN[+NUM|-ELN]] 8259d95b580SFranck Bui-Huu */ 826146a1439SMasami Hiramatsu int parse_line_range_desc(const char *arg, struct line_range *lr) 827631c9defSMasami Hiramatsu { 828e116dfa1SMasami Hiramatsu char *range, *file, *name = strdup(arg); 82921dd9ae5SFranck Bui-Huu int err; 8309d95b580SFranck Bui-Huu 83121dd9ae5SFranck Bui-Huu if (!name) 83221dd9ae5SFranck Bui-Huu return -ENOMEM; 83321dd9ae5SFranck Bui-Huu 83421dd9ae5SFranck Bui-Huu lr->start = 0; 83521dd9ae5SFranck Bui-Huu lr->end = INT_MAX; 83621dd9ae5SFranck Bui-Huu 83721dd9ae5SFranck Bui-Huu range = strchr(name, ':'); 83821dd9ae5SFranck Bui-Huu if (range) { 83921dd9ae5SFranck Bui-Huu *range++ = '\0'; 84021dd9ae5SFranck Bui-Huu 84121dd9ae5SFranck Bui-Huu err = parse_line_num(&range, &lr->start, "start line"); 84221dd9ae5SFranck Bui-Huu if (err) 84321dd9ae5SFranck Bui-Huu goto err; 84421dd9ae5SFranck Bui-Huu 84521dd9ae5SFranck Bui-Huu if (*range == '+' || *range == '-') { 84621dd9ae5SFranck Bui-Huu const char c = *range++; 84721dd9ae5SFranck Bui-Huu 84821dd9ae5SFranck Bui-Huu err = parse_line_num(&range, &lr->end, "end line"); 84921dd9ae5SFranck Bui-Huu if (err) 85021dd9ae5SFranck Bui-Huu goto err; 85121dd9ae5SFranck Bui-Huu 85221dd9ae5SFranck Bui-Huu if (c == '+') { 85321dd9ae5SFranck Bui-Huu lr->end += lr->start; 85421dd9ae5SFranck Bui-Huu /* 855dda4ab34SMasami Hiramatsu * Adjust the number of lines here. 856dda4ab34SMasami Hiramatsu * If the number of lines == 1, the 857dda4ab34SMasami Hiramatsu * the end of line should be equal to 858dda4ab34SMasami Hiramatsu * the start of line. 859dda4ab34SMasami Hiramatsu */ 86021dd9ae5SFranck Bui-Huu lr->end--; 86121dd9ae5SFranck Bui-Huu } 86221dd9ae5SFranck Bui-Huu } 86321dd9ae5SFranck Bui-Huu 864d3b63d7aSMasami Hiramatsu pr_debug("Line range is %d to %d\n", lr->start, lr->end); 86521dd9ae5SFranck Bui-Huu 86621dd9ae5SFranck Bui-Huu err = -EINVAL; 867d3b63d7aSMasami Hiramatsu if (lr->start > lr->end) { 868631c9defSMasami Hiramatsu semantic_error("Start line must be smaller" 869146a1439SMasami Hiramatsu " than end line.\n"); 87021dd9ae5SFranck Bui-Huu goto err; 871146a1439SMasami Hiramatsu } 87221dd9ae5SFranck Bui-Huu if (*range != '\0') { 87321dd9ae5SFranck Bui-Huu semantic_error("Tailing with invalid str '%s'.\n", range); 87421dd9ae5SFranck Bui-Huu goto err; 875146a1439SMasami Hiramatsu } 876d3b63d7aSMasami Hiramatsu } 87702b95dadSMasami Hiramatsu 878e116dfa1SMasami Hiramatsu file = strchr(name, '@'); 879e116dfa1SMasami Hiramatsu if (file) { 880e116dfa1SMasami Hiramatsu *file = '\0'; 881e116dfa1SMasami Hiramatsu lr->file = strdup(++file); 882e116dfa1SMasami Hiramatsu if (lr->file == NULL) { 883e116dfa1SMasami Hiramatsu err = -ENOMEM; 884e116dfa1SMasami Hiramatsu goto err; 885e116dfa1SMasami Hiramatsu } 886e116dfa1SMasami Hiramatsu lr->function = name; 887e116dfa1SMasami Hiramatsu } else if (strchr(name, '.')) 88821dd9ae5SFranck Bui-Huu lr->file = name; 889631c9defSMasami Hiramatsu else 89021dd9ae5SFranck Bui-Huu lr->function = name; 891146a1439SMasami Hiramatsu 892146a1439SMasami Hiramatsu return 0; 89321dd9ae5SFranck Bui-Huu err: 89421dd9ae5SFranck Bui-Huu free(name); 89521dd9ae5SFranck Bui-Huu return err; 896631c9defSMasami Hiramatsu } 897631c9defSMasami Hiramatsu 898b7702a21SMasami Hiramatsu /* Check the name is good for event/group */ 899b7702a21SMasami Hiramatsu static bool check_event_name(const char *name) 900b7702a21SMasami Hiramatsu { 901b7702a21SMasami Hiramatsu if (!isalpha(*name) && *name != '_') 902b7702a21SMasami Hiramatsu return false; 903b7702a21SMasami Hiramatsu while (*++name != '\0') { 904b7702a21SMasami Hiramatsu if (!isalpha(*name) && !isdigit(*name) && *name != '_') 905b7702a21SMasami Hiramatsu return false; 906b7702a21SMasami Hiramatsu } 907b7702a21SMasami Hiramatsu return true; 908b7702a21SMasami Hiramatsu } 909b7702a21SMasami Hiramatsu 91050656eecSMasami Hiramatsu /* Parse probepoint definition. */ 911146a1439SMasami Hiramatsu static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) 91250656eecSMasami Hiramatsu { 9134235b045SMasami Hiramatsu struct perf_probe_point *pp = &pev->point; 91450656eecSMasami Hiramatsu char *ptr, *tmp; 91550656eecSMasami Hiramatsu char c, nc = 0; 91650656eecSMasami Hiramatsu /* 91750656eecSMasami Hiramatsu * <Syntax> 9182a9c8c36SMasami Hiramatsu * perf probe [EVENT=]SRC[:LN|;PTN] 9192a9c8c36SMasami Hiramatsu * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] 920af663d75SMasami Hiramatsu * 921af663d75SMasami Hiramatsu * TODO:Group name support 92250656eecSMasami Hiramatsu */ 92350656eecSMasami Hiramatsu 9242a9c8c36SMasami Hiramatsu ptr = strpbrk(arg, ";=@+%"); 9252a9c8c36SMasami Hiramatsu if (ptr && *ptr == '=') { /* Event name */ 926af663d75SMasami Hiramatsu *ptr = '\0'; 927af663d75SMasami Hiramatsu tmp = ptr + 1; 928146a1439SMasami Hiramatsu if (strchr(arg, ':')) { 929146a1439SMasami Hiramatsu semantic_error("Group name is not supported yet.\n"); 930146a1439SMasami Hiramatsu return -ENOTSUP; 931146a1439SMasami Hiramatsu } 932146a1439SMasami Hiramatsu if (!check_event_name(arg)) { 933b7702a21SMasami Hiramatsu semantic_error("%s is bad for event name -it must " 934146a1439SMasami Hiramatsu "follow C symbol-naming rule.\n", arg); 935146a1439SMasami Hiramatsu return -EINVAL; 936146a1439SMasami Hiramatsu } 93702b95dadSMasami Hiramatsu pev->event = strdup(arg); 93802b95dadSMasami Hiramatsu if (pev->event == NULL) 93902b95dadSMasami Hiramatsu return -ENOMEM; 9404235b045SMasami Hiramatsu pev->group = NULL; 941af663d75SMasami Hiramatsu arg = tmp; 942af663d75SMasami Hiramatsu } 943af663d75SMasami Hiramatsu 9442a9c8c36SMasami Hiramatsu ptr = strpbrk(arg, ";:+@%"); 94550656eecSMasami Hiramatsu if (ptr) { 94650656eecSMasami Hiramatsu nc = *ptr; 94750656eecSMasami Hiramatsu *ptr++ = '\0'; 94850656eecSMasami Hiramatsu } 94950656eecSMasami Hiramatsu 95002b95dadSMasami Hiramatsu tmp = strdup(arg); 95102b95dadSMasami Hiramatsu if (tmp == NULL) 95202b95dadSMasami Hiramatsu return -ENOMEM; 95302b95dadSMasami Hiramatsu 95450656eecSMasami Hiramatsu /* Check arg is function or file and copy it */ 95502b95dadSMasami Hiramatsu if (strchr(tmp, '.')) /* File */ 95602b95dadSMasami Hiramatsu pp->file = tmp; 95750656eecSMasami Hiramatsu else /* Function */ 95802b95dadSMasami Hiramatsu pp->function = tmp; 95950656eecSMasami Hiramatsu 96050656eecSMasami Hiramatsu /* Parse other options */ 96150656eecSMasami Hiramatsu while (ptr) { 96250656eecSMasami Hiramatsu arg = ptr; 96350656eecSMasami Hiramatsu c = nc; 9642a9c8c36SMasami Hiramatsu if (c == ';') { /* Lazy pattern must be the last part */ 96502b95dadSMasami Hiramatsu pp->lazy_line = strdup(arg); 96602b95dadSMasami Hiramatsu if (pp->lazy_line == NULL) 96702b95dadSMasami Hiramatsu return -ENOMEM; 9682a9c8c36SMasami Hiramatsu break; 9692a9c8c36SMasami Hiramatsu } 9702a9c8c36SMasami Hiramatsu ptr = strpbrk(arg, ";:+@%"); 97150656eecSMasami Hiramatsu if (ptr) { 97250656eecSMasami Hiramatsu nc = *ptr; 97350656eecSMasami Hiramatsu *ptr++ = '\0'; 97450656eecSMasami Hiramatsu } 97550656eecSMasami Hiramatsu switch (c) { 97650656eecSMasami Hiramatsu case ':': /* Line number */ 97750656eecSMasami Hiramatsu pp->line = strtoul(arg, &tmp, 0); 978146a1439SMasami Hiramatsu if (*tmp != '\0') { 9792a9c8c36SMasami Hiramatsu semantic_error("There is non-digit char" 980146a1439SMasami Hiramatsu " in line number.\n"); 981146a1439SMasami Hiramatsu return -EINVAL; 982146a1439SMasami Hiramatsu } 98350656eecSMasami Hiramatsu break; 98450656eecSMasami Hiramatsu case '+': /* Byte offset from a symbol */ 98550656eecSMasami Hiramatsu pp->offset = strtoul(arg, &tmp, 0); 986146a1439SMasami Hiramatsu if (*tmp != '\0') { 9872a9c8c36SMasami Hiramatsu semantic_error("There is non-digit character" 988146a1439SMasami Hiramatsu " in offset.\n"); 989146a1439SMasami Hiramatsu return -EINVAL; 990146a1439SMasami Hiramatsu } 99150656eecSMasami Hiramatsu break; 99250656eecSMasami Hiramatsu case '@': /* File name */ 993146a1439SMasami Hiramatsu if (pp->file) { 994146a1439SMasami Hiramatsu semantic_error("SRC@SRC is not allowed.\n"); 995146a1439SMasami Hiramatsu return -EINVAL; 996146a1439SMasami Hiramatsu } 99702b95dadSMasami Hiramatsu pp->file = strdup(arg); 99802b95dadSMasami Hiramatsu if (pp->file == NULL) 99902b95dadSMasami Hiramatsu return -ENOMEM; 100050656eecSMasami Hiramatsu break; 100150656eecSMasami Hiramatsu case '%': /* Probe places */ 100250656eecSMasami Hiramatsu if (strcmp(arg, "return") == 0) { 100350656eecSMasami Hiramatsu pp->retprobe = 1; 1004146a1439SMasami Hiramatsu } else { /* Others not supported yet */ 1005146a1439SMasami Hiramatsu semantic_error("%%%s is not supported.\n", arg); 1006146a1439SMasami Hiramatsu return -ENOTSUP; 1007146a1439SMasami Hiramatsu } 100850656eecSMasami Hiramatsu break; 1009146a1439SMasami Hiramatsu default: /* Buggy case */ 1010146a1439SMasami Hiramatsu pr_err("This program has a bug at %s:%d.\n", 1011146a1439SMasami Hiramatsu __FILE__, __LINE__); 1012146a1439SMasami Hiramatsu return -ENOTSUP; 101350656eecSMasami Hiramatsu break; 101450656eecSMasami Hiramatsu } 101550656eecSMasami Hiramatsu } 101650656eecSMasami Hiramatsu 101750656eecSMasami Hiramatsu /* Exclusion check */ 1018146a1439SMasami Hiramatsu if (pp->lazy_line && pp->line) { 10190e43e5d2SMasami Hiramatsu semantic_error("Lazy pattern can't be used with" 10200e43e5d2SMasami Hiramatsu " line number.\n"); 1021146a1439SMasami Hiramatsu return -EINVAL; 1022146a1439SMasami Hiramatsu } 10232a9c8c36SMasami Hiramatsu 1024146a1439SMasami Hiramatsu if (pp->lazy_line && pp->offset) { 10250e43e5d2SMasami Hiramatsu semantic_error("Lazy pattern can't be used with offset.\n"); 1026146a1439SMasami Hiramatsu return -EINVAL; 1027146a1439SMasami Hiramatsu } 10282a9c8c36SMasami Hiramatsu 1029146a1439SMasami Hiramatsu if (pp->line && pp->offset) { 10300e43e5d2SMasami Hiramatsu semantic_error("Offset can't be used with line number.\n"); 1031146a1439SMasami Hiramatsu return -EINVAL; 1032146a1439SMasami Hiramatsu } 103350656eecSMasami Hiramatsu 1034146a1439SMasami Hiramatsu if (!pp->line && !pp->lazy_line && pp->file && !pp->function) { 10352a9c8c36SMasami Hiramatsu semantic_error("File always requires line number or " 10360e43e5d2SMasami Hiramatsu "lazy pattern.\n"); 1037146a1439SMasami Hiramatsu return -EINVAL; 1038146a1439SMasami Hiramatsu } 103950656eecSMasami Hiramatsu 1040146a1439SMasami Hiramatsu if (pp->offset && !pp->function) { 10410e43e5d2SMasami Hiramatsu semantic_error("Offset requires an entry function.\n"); 1042146a1439SMasami Hiramatsu return -EINVAL; 1043146a1439SMasami Hiramatsu } 104450656eecSMasami Hiramatsu 1045146a1439SMasami Hiramatsu if (pp->retprobe && !pp->function) { 10460e43e5d2SMasami Hiramatsu semantic_error("Return probe requires an entry function.\n"); 1047146a1439SMasami Hiramatsu return -EINVAL; 1048146a1439SMasami Hiramatsu } 104950656eecSMasami Hiramatsu 1050146a1439SMasami Hiramatsu if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) { 10512a9c8c36SMasami Hiramatsu semantic_error("Offset/Line/Lazy pattern can't be used with " 10520e43e5d2SMasami Hiramatsu "return probe.\n"); 1053146a1439SMasami Hiramatsu return -EINVAL; 1054146a1439SMasami Hiramatsu } 105550656eecSMasami Hiramatsu 10564235b045SMasami Hiramatsu pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n", 10572a9c8c36SMasami Hiramatsu pp->function, pp->file, pp->line, pp->offset, pp->retprobe, 10582a9c8c36SMasami Hiramatsu pp->lazy_line); 1059146a1439SMasami Hiramatsu return 0; 106050656eecSMasami Hiramatsu } 106150656eecSMasami Hiramatsu 10627df2f329SMasami Hiramatsu /* Parse perf-probe event argument */ 1063146a1439SMasami Hiramatsu static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) 10647df2f329SMasami Hiramatsu { 1065b2a3c12bSMasami Hiramatsu char *tmp, *goodname; 10667df2f329SMasami Hiramatsu struct perf_probe_arg_field **fieldp; 10677df2f329SMasami Hiramatsu 10687df2f329SMasami Hiramatsu pr_debug("parsing arg: %s into ", str); 10697df2f329SMasami Hiramatsu 107048481938SMasami Hiramatsu tmp = strchr(str, '='); 107148481938SMasami Hiramatsu if (tmp) { 107202b95dadSMasami Hiramatsu arg->name = strndup(str, tmp - str); 107302b95dadSMasami Hiramatsu if (arg->name == NULL) 107402b95dadSMasami Hiramatsu return -ENOMEM; 107511a1ca35SMasami Hiramatsu pr_debug("name:%s ", arg->name); 107648481938SMasami Hiramatsu str = tmp + 1; 107748481938SMasami Hiramatsu } 107848481938SMasami Hiramatsu 107911a1ca35SMasami Hiramatsu tmp = strchr(str, ':'); 108011a1ca35SMasami Hiramatsu if (tmp) { /* Type setting */ 108111a1ca35SMasami Hiramatsu *tmp = '\0'; 108202b95dadSMasami Hiramatsu arg->type = strdup(tmp + 1); 108302b95dadSMasami Hiramatsu if (arg->type == NULL) 108402b95dadSMasami Hiramatsu return -ENOMEM; 108511a1ca35SMasami Hiramatsu pr_debug("type:%s ", arg->type); 108611a1ca35SMasami Hiramatsu } 108711a1ca35SMasami Hiramatsu 1088b2a3c12bSMasami Hiramatsu tmp = strpbrk(str, "-.["); 10897df2f329SMasami Hiramatsu if (!is_c_varname(str) || !tmp) { 10907df2f329SMasami Hiramatsu /* A variable, register, symbol or special value */ 109102b95dadSMasami Hiramatsu arg->var = strdup(str); 109202b95dadSMasami Hiramatsu if (arg->var == NULL) 109302b95dadSMasami Hiramatsu return -ENOMEM; 109448481938SMasami Hiramatsu pr_debug("%s\n", arg->var); 1095146a1439SMasami Hiramatsu return 0; 10967df2f329SMasami Hiramatsu } 10977df2f329SMasami Hiramatsu 1098b2a3c12bSMasami Hiramatsu /* Structure fields or array element */ 109902b95dadSMasami Hiramatsu arg->var = strndup(str, tmp - str); 110002b95dadSMasami Hiramatsu if (arg->var == NULL) 110102b95dadSMasami Hiramatsu return -ENOMEM; 1102b2a3c12bSMasami Hiramatsu goodname = arg->var; 110348481938SMasami Hiramatsu pr_debug("%s, ", arg->var); 11047df2f329SMasami Hiramatsu fieldp = &arg->field; 11057df2f329SMasami Hiramatsu 11067df2f329SMasami Hiramatsu do { 1107e334016fSMasami Hiramatsu *fieldp = zalloc(sizeof(struct perf_probe_arg_field)); 1108e334016fSMasami Hiramatsu if (*fieldp == NULL) 1109e334016fSMasami Hiramatsu return -ENOMEM; 1110b2a3c12bSMasami Hiramatsu if (*tmp == '[') { /* Array */ 1111b2a3c12bSMasami Hiramatsu str = tmp; 1112b2a3c12bSMasami Hiramatsu (*fieldp)->index = strtol(str + 1, &tmp, 0); 1113b2a3c12bSMasami Hiramatsu (*fieldp)->ref = true; 1114b2a3c12bSMasami Hiramatsu if (*tmp != ']' || tmp == str + 1) { 1115b2a3c12bSMasami Hiramatsu semantic_error("Array index must be a" 1116b2a3c12bSMasami Hiramatsu " number.\n"); 1117b2a3c12bSMasami Hiramatsu return -EINVAL; 1118b2a3c12bSMasami Hiramatsu } 1119b2a3c12bSMasami Hiramatsu tmp++; 1120b2a3c12bSMasami Hiramatsu if (*tmp == '\0') 1121b2a3c12bSMasami Hiramatsu tmp = NULL; 1122b2a3c12bSMasami Hiramatsu } else { /* Structure */ 11237df2f329SMasami Hiramatsu if (*tmp == '.') { 11247df2f329SMasami Hiramatsu str = tmp + 1; 11257df2f329SMasami Hiramatsu (*fieldp)->ref = false; 11267df2f329SMasami Hiramatsu } else if (tmp[1] == '>') { 11277df2f329SMasami Hiramatsu str = tmp + 2; 11287df2f329SMasami Hiramatsu (*fieldp)->ref = true; 1129146a1439SMasami Hiramatsu } else { 1130b2a3c12bSMasami Hiramatsu semantic_error("Argument parse error: %s\n", 1131b2a3c12bSMasami Hiramatsu str); 1132146a1439SMasami Hiramatsu return -EINVAL; 1133146a1439SMasami Hiramatsu } 1134b2a3c12bSMasami Hiramatsu tmp = strpbrk(str, "-.["); 1135b2a3c12bSMasami Hiramatsu } 11367df2f329SMasami Hiramatsu if (tmp) { 113702b95dadSMasami Hiramatsu (*fieldp)->name = strndup(str, tmp - str); 113802b95dadSMasami Hiramatsu if ((*fieldp)->name == NULL) 113902b95dadSMasami Hiramatsu return -ENOMEM; 1140b2a3c12bSMasami Hiramatsu if (*str != '[') 1141b2a3c12bSMasami Hiramatsu goodname = (*fieldp)->name; 11427df2f329SMasami Hiramatsu pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref); 11437df2f329SMasami Hiramatsu fieldp = &(*fieldp)->next; 11447df2f329SMasami Hiramatsu } 11457df2f329SMasami Hiramatsu } while (tmp); 114602b95dadSMasami Hiramatsu (*fieldp)->name = strdup(str); 114702b95dadSMasami Hiramatsu if ((*fieldp)->name == NULL) 114802b95dadSMasami Hiramatsu return -ENOMEM; 1149b2a3c12bSMasami Hiramatsu if (*str != '[') 1150b2a3c12bSMasami Hiramatsu goodname = (*fieldp)->name; 11517df2f329SMasami Hiramatsu pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref); 1152df0faf4bSMasami Hiramatsu 1153b2a3c12bSMasami Hiramatsu /* If no name is specified, set the last field name (not array index)*/ 115402b95dadSMasami Hiramatsu if (!arg->name) { 1155b2a3c12bSMasami Hiramatsu arg->name = strdup(goodname); 115602b95dadSMasami Hiramatsu if (arg->name == NULL) 115702b95dadSMasami Hiramatsu return -ENOMEM; 115802b95dadSMasami Hiramatsu } 1159146a1439SMasami Hiramatsu return 0; 11607df2f329SMasami Hiramatsu } 11617df2f329SMasami Hiramatsu 11624235b045SMasami Hiramatsu /* Parse perf-probe event command */ 1163146a1439SMasami Hiramatsu int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev) 116450656eecSMasami Hiramatsu { 1165e1c01d61SMasami Hiramatsu char **argv; 1166146a1439SMasami Hiramatsu int argc, i, ret = 0; 1167fac13fd5SMasami Hiramatsu 11684235b045SMasami Hiramatsu argv = argv_split(cmd, &argc); 1169146a1439SMasami Hiramatsu if (!argv) { 1170146a1439SMasami Hiramatsu pr_debug("Failed to split arguments.\n"); 1171146a1439SMasami Hiramatsu return -ENOMEM; 1172146a1439SMasami Hiramatsu } 1173146a1439SMasami Hiramatsu if (argc - 1 > MAX_PROBE_ARGS) { 1174146a1439SMasami Hiramatsu semantic_error("Too many probe arguments (%d).\n", argc - 1); 1175146a1439SMasami Hiramatsu ret = -ERANGE; 1176146a1439SMasami Hiramatsu goto out; 1177146a1439SMasami Hiramatsu } 117850656eecSMasami Hiramatsu /* Parse probe point */ 1179146a1439SMasami Hiramatsu ret = parse_perf_probe_point(argv[0], pev); 1180146a1439SMasami Hiramatsu if (ret < 0) 1181146a1439SMasami Hiramatsu goto out; 118250656eecSMasami Hiramatsu 1183e1c01d61SMasami Hiramatsu /* Copy arguments and ensure return probe has no C argument */ 11844235b045SMasami Hiramatsu pev->nargs = argc - 1; 1185e334016fSMasami Hiramatsu pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs); 1186e334016fSMasami Hiramatsu if (pev->args == NULL) { 1187e334016fSMasami Hiramatsu ret = -ENOMEM; 1188e334016fSMasami Hiramatsu goto out; 1189e334016fSMasami Hiramatsu } 1190146a1439SMasami Hiramatsu for (i = 0; i < pev->nargs && ret >= 0; i++) { 1191146a1439SMasami Hiramatsu ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]); 1192146a1439SMasami Hiramatsu if (ret >= 0 && 1193146a1439SMasami Hiramatsu is_c_varname(pev->args[i].var) && pev->point.retprobe) { 11944235b045SMasami Hiramatsu semantic_error("You can't specify local variable for" 1195146a1439SMasami Hiramatsu " kretprobe.\n"); 1196146a1439SMasami Hiramatsu ret = -EINVAL; 1197e1c01d61SMasami Hiramatsu } 1198146a1439SMasami Hiramatsu } 1199146a1439SMasami Hiramatsu out: 1200e1c01d61SMasami Hiramatsu argv_free(argv); 1201146a1439SMasami Hiramatsu 1202146a1439SMasami Hiramatsu return ret; 120350656eecSMasami Hiramatsu } 120450656eecSMasami Hiramatsu 12054235b045SMasami Hiramatsu /* Return true if this perf_probe_event requires debuginfo */ 12064235b045SMasami Hiramatsu bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) 12074de189feSMasami Hiramatsu { 12084235b045SMasami Hiramatsu int i; 12094235b045SMasami Hiramatsu 12104235b045SMasami Hiramatsu if (pev->point.file || pev->point.line || pev->point.lazy_line) 12114235b045SMasami Hiramatsu return true; 12124235b045SMasami Hiramatsu 12134235b045SMasami Hiramatsu for (i = 0; i < pev->nargs; i++) 121448481938SMasami Hiramatsu if (is_c_varname(pev->args[i].var)) 12154235b045SMasami Hiramatsu return true; 12164235b045SMasami Hiramatsu 12174235b045SMasami Hiramatsu return false; 12184235b045SMasami Hiramatsu } 12194235b045SMasami Hiramatsu 12200e60836bSSrikar Dronamraju /* Parse probe_events event into struct probe_point */ 12210e60836bSSrikar Dronamraju static int parse_probe_trace_command(const char *cmd, 12220e60836bSSrikar Dronamraju struct probe_trace_event *tev) 12234235b045SMasami Hiramatsu { 12240e60836bSSrikar Dronamraju struct probe_trace_point *tp = &tev->point; 12254de189feSMasami Hiramatsu char pr; 12264de189feSMasami Hiramatsu char *p; 1227bcbd0040SIrina Tirdea char *argv0_str = NULL, *fmt, *fmt1_str, *fmt2_str, *fmt3_str; 12284de189feSMasami Hiramatsu int ret, i, argc; 12294de189feSMasami Hiramatsu char **argv; 12304de189feSMasami Hiramatsu 12310e60836bSSrikar Dronamraju pr_debug("Parsing probe_events: %s\n", cmd); 12324235b045SMasami Hiramatsu argv = argv_split(cmd, &argc); 1233146a1439SMasami Hiramatsu if (!argv) { 1234146a1439SMasami Hiramatsu pr_debug("Failed to split arguments.\n"); 1235146a1439SMasami Hiramatsu return -ENOMEM; 1236146a1439SMasami Hiramatsu } 1237146a1439SMasami Hiramatsu if (argc < 2) { 1238146a1439SMasami Hiramatsu semantic_error("Too few probe arguments.\n"); 1239146a1439SMasami Hiramatsu ret = -ERANGE; 1240146a1439SMasami Hiramatsu goto out; 1241146a1439SMasami Hiramatsu } 12424de189feSMasami Hiramatsu 12434de189feSMasami Hiramatsu /* Scan event and group name. */ 1244bcbd0040SIrina Tirdea argv0_str = strdup(argv[0]); 1245bcbd0040SIrina Tirdea if (argv0_str == NULL) { 1246bcbd0040SIrina Tirdea ret = -ENOMEM; 1247bcbd0040SIrina Tirdea goto out; 1248bcbd0040SIrina Tirdea } 1249bcbd0040SIrina Tirdea fmt1_str = strtok_r(argv0_str, ":", &fmt); 1250bcbd0040SIrina Tirdea fmt2_str = strtok_r(NULL, "/", &fmt); 1251bcbd0040SIrina Tirdea fmt3_str = strtok_r(NULL, " \t", &fmt); 1252bcbd0040SIrina Tirdea if (fmt1_str == NULL || strlen(fmt1_str) != 1 || fmt2_str == NULL 1253bcbd0040SIrina Tirdea || fmt3_str == NULL) { 1254146a1439SMasami Hiramatsu semantic_error("Failed to parse event name: %s\n", argv[0]); 1255146a1439SMasami Hiramatsu ret = -EINVAL; 1256146a1439SMasami Hiramatsu goto out; 1257146a1439SMasami Hiramatsu } 1258bcbd0040SIrina Tirdea pr = fmt1_str[0]; 1259bcbd0040SIrina Tirdea tev->group = strdup(fmt2_str); 1260bcbd0040SIrina Tirdea tev->event = strdup(fmt3_str); 1261bcbd0040SIrina Tirdea if (tev->group == NULL || tev->event == NULL) { 1262bcbd0040SIrina Tirdea ret = -ENOMEM; 1263bcbd0040SIrina Tirdea goto out; 1264bcbd0040SIrina Tirdea } 12654235b045SMasami Hiramatsu pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr); 12664de189feSMasami Hiramatsu 12674235b045SMasami Hiramatsu tp->retprobe = (pr == 'r'); 12684de189feSMasami Hiramatsu 1269190b57fcSMasami Hiramatsu /* Scan module name(if there), function name and offset */ 1270190b57fcSMasami Hiramatsu p = strchr(argv[1], ':'); 1271190b57fcSMasami Hiramatsu if (p) { 1272190b57fcSMasami Hiramatsu tp->module = strndup(argv[1], p - argv[1]); 1273190b57fcSMasami Hiramatsu p++; 1274190b57fcSMasami Hiramatsu } else 1275190b57fcSMasami Hiramatsu p = argv[1]; 1276bcbd0040SIrina Tirdea fmt1_str = strtok_r(p, "+", &fmt); 1277bcbd0040SIrina Tirdea tp->symbol = strdup(fmt1_str); 1278bcbd0040SIrina Tirdea if (tp->symbol == NULL) { 1279bcbd0040SIrina Tirdea ret = -ENOMEM; 1280bcbd0040SIrina Tirdea goto out; 1281bcbd0040SIrina Tirdea } 1282bcbd0040SIrina Tirdea fmt2_str = strtok_r(NULL, "", &fmt); 1283bcbd0040SIrina Tirdea if (fmt2_str == NULL) 12844235b045SMasami Hiramatsu tp->offset = 0; 1285bcbd0040SIrina Tirdea else 1286bcbd0040SIrina Tirdea tp->offset = strtoul(fmt2_str, NULL, 10); 12874de189feSMasami Hiramatsu 12884235b045SMasami Hiramatsu tev->nargs = argc - 2; 12890e60836bSSrikar Dronamraju tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); 1290e334016fSMasami Hiramatsu if (tev->args == NULL) { 1291e334016fSMasami Hiramatsu ret = -ENOMEM; 1292e334016fSMasami Hiramatsu goto out; 1293e334016fSMasami Hiramatsu } 12944235b045SMasami Hiramatsu for (i = 0; i < tev->nargs; i++) { 12954de189feSMasami Hiramatsu p = strchr(argv[i + 2], '='); 12964de189feSMasami Hiramatsu if (p) /* We don't need which register is assigned. */ 12974235b045SMasami Hiramatsu *p++ = '\0'; 12984235b045SMasami Hiramatsu else 12994235b045SMasami Hiramatsu p = argv[i + 2]; 130002b95dadSMasami Hiramatsu tev->args[i].name = strdup(argv[i + 2]); 13014235b045SMasami Hiramatsu /* TODO: parse regs and offset */ 130202b95dadSMasami Hiramatsu tev->args[i].value = strdup(p); 130302b95dadSMasami Hiramatsu if (tev->args[i].name == NULL || tev->args[i].value == NULL) { 130402b95dadSMasami Hiramatsu ret = -ENOMEM; 130502b95dadSMasami Hiramatsu goto out; 130602b95dadSMasami Hiramatsu } 13074de189feSMasami Hiramatsu } 1308146a1439SMasami Hiramatsu ret = 0; 1309146a1439SMasami Hiramatsu out: 1310bcbd0040SIrina Tirdea free(argv0_str); 13114de189feSMasami Hiramatsu argv_free(argv); 1312146a1439SMasami Hiramatsu return ret; 13134de189feSMasami Hiramatsu } 13144de189feSMasami Hiramatsu 13157df2f329SMasami Hiramatsu /* Compose only probe arg */ 13167df2f329SMasami Hiramatsu int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len) 13177df2f329SMasami Hiramatsu { 13187df2f329SMasami Hiramatsu struct perf_probe_arg_field *field = pa->field; 13197df2f329SMasami Hiramatsu int ret; 13207df2f329SMasami Hiramatsu char *tmp = buf; 13217df2f329SMasami Hiramatsu 132248481938SMasami Hiramatsu if (pa->name && pa->var) 132348481938SMasami Hiramatsu ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var); 132448481938SMasami Hiramatsu else 132548481938SMasami Hiramatsu ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var); 13267df2f329SMasami Hiramatsu if (ret <= 0) 13277df2f329SMasami Hiramatsu goto error; 13287df2f329SMasami Hiramatsu tmp += ret; 13297df2f329SMasami Hiramatsu len -= ret; 13307df2f329SMasami Hiramatsu 13317df2f329SMasami Hiramatsu while (field) { 1332b2a3c12bSMasami Hiramatsu if (field->name[0] == '[') 1333b2a3c12bSMasami Hiramatsu ret = e_snprintf(tmp, len, "%s", field->name); 1334b2a3c12bSMasami Hiramatsu else 1335b2a3c12bSMasami Hiramatsu ret = e_snprintf(tmp, len, "%s%s", 1336b2a3c12bSMasami Hiramatsu field->ref ? "->" : ".", field->name); 13377df2f329SMasami Hiramatsu if (ret <= 0) 13387df2f329SMasami Hiramatsu goto error; 13397df2f329SMasami Hiramatsu tmp += ret; 13407df2f329SMasami Hiramatsu len -= ret; 13417df2f329SMasami Hiramatsu field = field->next; 13427df2f329SMasami Hiramatsu } 134311a1ca35SMasami Hiramatsu 134411a1ca35SMasami Hiramatsu if (pa->type) { 134511a1ca35SMasami Hiramatsu ret = e_snprintf(tmp, len, ":%s", pa->type); 134611a1ca35SMasami Hiramatsu if (ret <= 0) 134711a1ca35SMasami Hiramatsu goto error; 134811a1ca35SMasami Hiramatsu tmp += ret; 134911a1ca35SMasami Hiramatsu len -= ret; 135011a1ca35SMasami Hiramatsu } 135111a1ca35SMasami Hiramatsu 13527df2f329SMasami Hiramatsu return tmp - buf; 13537df2f329SMasami Hiramatsu error: 13540e43e5d2SMasami Hiramatsu pr_debug("Failed to synthesize perf probe argument: %s\n", 1355146a1439SMasami Hiramatsu strerror(-ret)); 1356146a1439SMasami Hiramatsu return ret; 13577df2f329SMasami Hiramatsu } 13587df2f329SMasami Hiramatsu 13594235b045SMasami Hiramatsu /* Compose only probe point (not argument) */ 13604235b045SMasami Hiramatsu static char *synthesize_perf_probe_point(struct perf_probe_point *pp) 136150656eecSMasami Hiramatsu { 1362fb1587d8SMasami Hiramatsu char *buf, *tmp; 1363fb1587d8SMasami Hiramatsu char offs[32] = "", line[32] = "", file[32] = ""; 1364fb1587d8SMasami Hiramatsu int ret, len; 136550656eecSMasami Hiramatsu 1366e334016fSMasami Hiramatsu buf = zalloc(MAX_CMDLEN); 1367e334016fSMasami Hiramatsu if (buf == NULL) { 1368e334016fSMasami Hiramatsu ret = -ENOMEM; 1369e334016fSMasami Hiramatsu goto error; 1370e334016fSMasami Hiramatsu } 13714de189feSMasami Hiramatsu if (pp->offset) { 1372fb1587d8SMasami Hiramatsu ret = e_snprintf(offs, 32, "+%lu", pp->offset); 13734de189feSMasami Hiramatsu if (ret <= 0) 13744de189feSMasami Hiramatsu goto error; 13754de189feSMasami Hiramatsu } 13764de189feSMasami Hiramatsu if (pp->line) { 1377fb1587d8SMasami Hiramatsu ret = e_snprintf(line, 32, ":%d", pp->line); 1378fb1587d8SMasami Hiramatsu if (ret <= 0) 1379fb1587d8SMasami Hiramatsu goto error; 1380fb1587d8SMasami Hiramatsu } 1381fb1587d8SMasami Hiramatsu if (pp->file) { 138232ae2adeSFranck Bui-Huu tmp = pp->file; 138332ae2adeSFranck Bui-Huu len = strlen(tmp); 138432ae2adeSFranck Bui-Huu if (len > 30) { 138532ae2adeSFranck Bui-Huu tmp = strchr(pp->file + len - 30, '/'); 138632ae2adeSFranck Bui-Huu tmp = tmp ? tmp + 1 : pp->file + len - 30; 138732ae2adeSFranck Bui-Huu } 138832ae2adeSFranck Bui-Huu ret = e_snprintf(file, 32, "@%s", tmp); 13894de189feSMasami Hiramatsu if (ret <= 0) 13904de189feSMasami Hiramatsu goto error; 13914de189feSMasami Hiramatsu } 13924de189feSMasami Hiramatsu 13934de189feSMasami Hiramatsu if (pp->function) 1394fb1587d8SMasami Hiramatsu ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function, 1395fb1587d8SMasami Hiramatsu offs, pp->retprobe ? "%return" : "", line, 1396fb1587d8SMasami Hiramatsu file); 13974de189feSMasami Hiramatsu else 1398fb1587d8SMasami Hiramatsu ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line); 13994235b045SMasami Hiramatsu if (ret <= 0) 14004235b045SMasami Hiramatsu goto error; 14014235b045SMasami Hiramatsu 14024235b045SMasami Hiramatsu return buf; 14034235b045SMasami Hiramatsu error: 14040e43e5d2SMasami Hiramatsu pr_debug("Failed to synthesize perf probe point: %s\n", 1405146a1439SMasami Hiramatsu strerror(-ret)); 1406146a1439SMasami Hiramatsu free(buf); 1407146a1439SMasami Hiramatsu return NULL; 14084235b045SMasami Hiramatsu } 14094235b045SMasami Hiramatsu 14104235b045SMasami Hiramatsu #if 0 14114235b045SMasami Hiramatsu char *synthesize_perf_probe_command(struct perf_probe_event *pev) 14124235b045SMasami Hiramatsu { 14134235b045SMasami Hiramatsu char *buf; 14144235b045SMasami Hiramatsu int i, len, ret; 14154235b045SMasami Hiramatsu 14164235b045SMasami Hiramatsu buf = synthesize_perf_probe_point(&pev->point); 14174235b045SMasami Hiramatsu if (!buf) 14184235b045SMasami Hiramatsu return NULL; 14194235b045SMasami Hiramatsu 14204235b045SMasami Hiramatsu len = strlen(buf); 14214235b045SMasami Hiramatsu for (i = 0; i < pev->nargs; i++) { 14224235b045SMasami Hiramatsu ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s", 14234235b045SMasami Hiramatsu pev->args[i].name); 14247ef17aafSMasami Hiramatsu if (ret <= 0) { 14254235b045SMasami Hiramatsu free(buf); 14264235b045SMasami Hiramatsu return NULL; 14277ef17aafSMasami Hiramatsu } 14284235b045SMasami Hiramatsu len += ret; 14297ef17aafSMasami Hiramatsu } 143050656eecSMasami Hiramatsu 14314235b045SMasami Hiramatsu return buf; 14324235b045SMasami Hiramatsu } 14334235b045SMasami Hiramatsu #endif 14344235b045SMasami Hiramatsu 14350e60836bSSrikar Dronamraju static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref, 14364235b045SMasami Hiramatsu char **buf, size_t *buflen, 14374235b045SMasami Hiramatsu int depth) 14387ef17aafSMasami Hiramatsu { 14394235b045SMasami Hiramatsu int ret; 14404235b045SMasami Hiramatsu if (ref->next) { 14410e60836bSSrikar Dronamraju depth = __synthesize_probe_trace_arg_ref(ref->next, buf, 14424235b045SMasami Hiramatsu buflen, depth + 1); 14434235b045SMasami Hiramatsu if (depth < 0) 14444235b045SMasami Hiramatsu goto out; 14454235b045SMasami Hiramatsu } 14464235b045SMasami Hiramatsu 14474235b045SMasami Hiramatsu ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset); 14484235b045SMasami Hiramatsu if (ret < 0) 14494235b045SMasami Hiramatsu depth = ret; 14504235b045SMasami Hiramatsu else { 14514235b045SMasami Hiramatsu *buf += ret; 14524235b045SMasami Hiramatsu *buflen -= ret; 14534235b045SMasami Hiramatsu } 14544235b045SMasami Hiramatsu out: 14554235b045SMasami Hiramatsu return depth; 14564235b045SMasami Hiramatsu 14574235b045SMasami Hiramatsu } 14584235b045SMasami Hiramatsu 14590e60836bSSrikar Dronamraju static int synthesize_probe_trace_arg(struct probe_trace_arg *arg, 14604235b045SMasami Hiramatsu char *buf, size_t buflen) 14614235b045SMasami Hiramatsu { 14620e60836bSSrikar Dronamraju struct probe_trace_arg_ref *ref = arg->ref; 14634235b045SMasami Hiramatsu int ret, depth = 0; 14644235b045SMasami Hiramatsu char *tmp = buf; 14654235b045SMasami Hiramatsu 14664235b045SMasami Hiramatsu /* Argument name or separator */ 14674235b045SMasami Hiramatsu if (arg->name) 14684235b045SMasami Hiramatsu ret = e_snprintf(buf, buflen, " %s=", arg->name); 14694235b045SMasami Hiramatsu else 14704235b045SMasami Hiramatsu ret = e_snprintf(buf, buflen, " "); 14714235b045SMasami Hiramatsu if (ret < 0) 14724235b045SMasami Hiramatsu return ret; 14734235b045SMasami Hiramatsu buf += ret; 14744235b045SMasami Hiramatsu buflen -= ret; 14754235b045SMasami Hiramatsu 1476b7dcb857SMasami Hiramatsu /* Special case: @XXX */ 1477b7dcb857SMasami Hiramatsu if (arg->value[0] == '@' && arg->ref) 1478b7dcb857SMasami Hiramatsu ref = ref->next; 1479b7dcb857SMasami Hiramatsu 14804235b045SMasami Hiramatsu /* Dereferencing arguments */ 1481b7dcb857SMasami Hiramatsu if (ref) { 14820e60836bSSrikar Dronamraju depth = __synthesize_probe_trace_arg_ref(ref, &buf, 14834235b045SMasami Hiramatsu &buflen, 1); 14844235b045SMasami Hiramatsu if (depth < 0) 14854235b045SMasami Hiramatsu return depth; 14864235b045SMasami Hiramatsu } 14874235b045SMasami Hiramatsu 14884235b045SMasami Hiramatsu /* Print argument value */ 1489b7dcb857SMasami Hiramatsu if (arg->value[0] == '@' && arg->ref) 1490b7dcb857SMasami Hiramatsu ret = e_snprintf(buf, buflen, "%s%+ld", arg->value, 1491b7dcb857SMasami Hiramatsu arg->ref->offset); 1492b7dcb857SMasami Hiramatsu else 14934235b045SMasami Hiramatsu ret = e_snprintf(buf, buflen, "%s", arg->value); 14944235b045SMasami Hiramatsu if (ret < 0) 14954235b045SMasami Hiramatsu return ret; 14964235b045SMasami Hiramatsu buf += ret; 14974235b045SMasami Hiramatsu buflen -= ret; 14984235b045SMasami Hiramatsu 14994235b045SMasami Hiramatsu /* Closing */ 15004235b045SMasami Hiramatsu while (depth--) { 15014235b045SMasami Hiramatsu ret = e_snprintf(buf, buflen, ")"); 15024235b045SMasami Hiramatsu if (ret < 0) 15034235b045SMasami Hiramatsu return ret; 15044235b045SMasami Hiramatsu buf += ret; 15054235b045SMasami Hiramatsu buflen -= ret; 15064235b045SMasami Hiramatsu } 15074984912eSMasami Hiramatsu /* Print argument type */ 15084984912eSMasami Hiramatsu if (arg->type) { 15094984912eSMasami Hiramatsu ret = e_snprintf(buf, buflen, ":%s", arg->type); 15104984912eSMasami Hiramatsu if (ret <= 0) 15114984912eSMasami Hiramatsu return ret; 15124984912eSMasami Hiramatsu buf += ret; 15134984912eSMasami Hiramatsu } 15144235b045SMasami Hiramatsu 15154235b045SMasami Hiramatsu return buf - tmp; 15164235b045SMasami Hiramatsu } 15174235b045SMasami Hiramatsu 15180e60836bSSrikar Dronamraju char *synthesize_probe_trace_command(struct probe_trace_event *tev) 15194235b045SMasami Hiramatsu { 15200e60836bSSrikar Dronamraju struct probe_trace_point *tp = &tev->point; 15217ef17aafSMasami Hiramatsu char *buf; 15227ef17aafSMasami Hiramatsu int i, len, ret; 15237ef17aafSMasami Hiramatsu 1524e334016fSMasami Hiramatsu buf = zalloc(MAX_CMDLEN); 1525e334016fSMasami Hiramatsu if (buf == NULL) 1526e334016fSMasami Hiramatsu return NULL; 1527e334016fSMasami Hiramatsu 1528225466f1SSrikar Dronamraju if (tev->uprobes) 1529225466f1SSrikar Dronamraju len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s:%s", 1530225466f1SSrikar Dronamraju tp->retprobe ? 'r' : 'p', 1531225466f1SSrikar Dronamraju tev->group, tev->event, 1532225466f1SSrikar Dronamraju tp->module, tp->symbol); 1533225466f1SSrikar Dronamraju else 1534190b57fcSMasami Hiramatsu len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu", 15354235b045SMasami Hiramatsu tp->retprobe ? 'r' : 'p', 15364235b045SMasami Hiramatsu tev->group, tev->event, 1537190b57fcSMasami Hiramatsu tp->module ?: "", tp->module ? ":" : "", 15384235b045SMasami Hiramatsu tp->symbol, tp->offset); 1539225466f1SSrikar Dronamraju 15404235b045SMasami Hiramatsu if (len <= 0) 15414235b045SMasami Hiramatsu goto error; 15427ef17aafSMasami Hiramatsu 15434235b045SMasami Hiramatsu for (i = 0; i < tev->nargs; i++) { 15440e60836bSSrikar Dronamraju ret = synthesize_probe_trace_arg(&tev->args[i], buf + len, 15454235b045SMasami Hiramatsu MAX_CMDLEN - len); 15464de189feSMasami Hiramatsu if (ret <= 0) 154750656eecSMasami Hiramatsu goto error; 154850656eecSMasami Hiramatsu len += ret; 154950656eecSMasami Hiramatsu } 155050656eecSMasami Hiramatsu 15514235b045SMasami Hiramatsu return buf; 155250656eecSMasami Hiramatsu error: 15534235b045SMasami Hiramatsu free(buf); 15544235b045SMasami Hiramatsu return NULL; 155550656eecSMasami Hiramatsu } 155650656eecSMasami Hiramatsu 15570e60836bSSrikar Dronamraju static int convert_to_perf_probe_event(struct probe_trace_event *tev, 1558225466f1SSrikar Dronamraju struct perf_probe_event *pev, bool is_kprobe) 15594de189feSMasami Hiramatsu { 156002b95dadSMasami Hiramatsu char buf[64] = ""; 1561146a1439SMasami Hiramatsu int i, ret; 15624de189feSMasami Hiramatsu 15634b4da7f7SMasami Hiramatsu /* Convert event/group name */ 156402b95dadSMasami Hiramatsu pev->event = strdup(tev->event); 156502b95dadSMasami Hiramatsu pev->group = strdup(tev->group); 156602b95dadSMasami Hiramatsu if (pev->event == NULL || pev->group == NULL) 156702b95dadSMasami Hiramatsu return -ENOMEM; 1568fb1587d8SMasami Hiramatsu 15694b4da7f7SMasami Hiramatsu /* Convert trace_point to probe_point */ 1570225466f1SSrikar Dronamraju if (is_kprobe) 15710e60836bSSrikar Dronamraju ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point); 1572225466f1SSrikar Dronamraju else 1573225466f1SSrikar Dronamraju ret = convert_to_perf_probe_point(&tev->point, &pev->point); 1574225466f1SSrikar Dronamraju 1575146a1439SMasami Hiramatsu if (ret < 0) 1576146a1439SMasami Hiramatsu return ret; 15774b4da7f7SMasami Hiramatsu 15784235b045SMasami Hiramatsu /* Convert trace_arg to probe_arg */ 15794235b045SMasami Hiramatsu pev->nargs = tev->nargs; 1580e334016fSMasami Hiramatsu pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs); 1581e334016fSMasami Hiramatsu if (pev->args == NULL) 1582e334016fSMasami Hiramatsu return -ENOMEM; 158302b95dadSMasami Hiramatsu for (i = 0; i < tev->nargs && ret >= 0; i++) { 15844235b045SMasami Hiramatsu if (tev->args[i].name) 158502b95dadSMasami Hiramatsu pev->args[i].name = strdup(tev->args[i].name); 15864235b045SMasami Hiramatsu else { 15870e60836bSSrikar Dronamraju ret = synthesize_probe_trace_arg(&tev->args[i], 1588146a1439SMasami Hiramatsu buf, 64); 158902b95dadSMasami Hiramatsu pev->args[i].name = strdup(buf); 159002b95dadSMasami Hiramatsu } 159102b95dadSMasami Hiramatsu if (pev->args[i].name == NULL && ret >= 0) 159202b95dadSMasami Hiramatsu ret = -ENOMEM; 15934de189feSMasami Hiramatsu } 1594146a1439SMasami Hiramatsu 1595146a1439SMasami Hiramatsu if (ret < 0) 1596146a1439SMasami Hiramatsu clear_perf_probe_event(pev); 1597146a1439SMasami Hiramatsu 1598146a1439SMasami Hiramatsu return ret; 15994235b045SMasami Hiramatsu } 16004de189feSMasami Hiramatsu 16014235b045SMasami Hiramatsu void clear_perf_probe_event(struct perf_probe_event *pev) 16024235b045SMasami Hiramatsu { 16034235b045SMasami Hiramatsu struct perf_probe_point *pp = &pev->point; 16047df2f329SMasami Hiramatsu struct perf_probe_arg_field *field, *next; 16054235b045SMasami Hiramatsu int i; 16064de189feSMasami Hiramatsu 16074235b045SMasami Hiramatsu free(pev->event); 16084235b045SMasami Hiramatsu free(pev->group); 16094235b045SMasami Hiramatsu free(pp->file); 16104235b045SMasami Hiramatsu free(pp->function); 16114235b045SMasami Hiramatsu free(pp->lazy_line); 1612f5385650SArnaldo Carvalho de Melo 16137df2f329SMasami Hiramatsu for (i = 0; i < pev->nargs; i++) { 16144235b045SMasami Hiramatsu free(pev->args[i].name); 161548481938SMasami Hiramatsu free(pev->args[i].var); 161611a1ca35SMasami Hiramatsu free(pev->args[i].type); 16177df2f329SMasami Hiramatsu field = pev->args[i].field; 16187df2f329SMasami Hiramatsu while (field) { 16197df2f329SMasami Hiramatsu next = field->next; 162074cf249dSArnaldo Carvalho de Melo zfree(&field->name); 16217df2f329SMasami Hiramatsu free(field); 16227df2f329SMasami Hiramatsu field = next; 16237df2f329SMasami Hiramatsu } 16247df2f329SMasami Hiramatsu } 16254235b045SMasami Hiramatsu free(pev->args); 16264235b045SMasami Hiramatsu memset(pev, 0, sizeof(*pev)); 16274235b045SMasami Hiramatsu } 16284235b045SMasami Hiramatsu 16290e60836bSSrikar Dronamraju static void clear_probe_trace_event(struct probe_trace_event *tev) 16304235b045SMasami Hiramatsu { 16310e60836bSSrikar Dronamraju struct probe_trace_arg_ref *ref, *next; 16324235b045SMasami Hiramatsu int i; 16334235b045SMasami Hiramatsu 16344235b045SMasami Hiramatsu free(tev->event); 16354235b045SMasami Hiramatsu free(tev->group); 16364235b045SMasami Hiramatsu free(tev->point.symbol); 1637190b57fcSMasami Hiramatsu free(tev->point.module); 16384235b045SMasami Hiramatsu for (i = 0; i < tev->nargs; i++) { 16394235b045SMasami Hiramatsu free(tev->args[i].name); 16404235b045SMasami Hiramatsu free(tev->args[i].value); 16414984912eSMasami Hiramatsu free(tev->args[i].type); 16424235b045SMasami Hiramatsu ref = tev->args[i].ref; 16434235b045SMasami Hiramatsu while (ref) { 16444235b045SMasami Hiramatsu next = ref->next; 16454235b045SMasami Hiramatsu free(ref); 16464235b045SMasami Hiramatsu ref = next; 16474235b045SMasami Hiramatsu } 16484235b045SMasami Hiramatsu } 16494235b045SMasami Hiramatsu free(tev->args); 16504235b045SMasami Hiramatsu memset(tev, 0, sizeof(*tev)); 16514de189feSMasami Hiramatsu } 16524de189feSMasami Hiramatsu 1653225466f1SSrikar Dronamraju static void print_warn_msg(const char *file, bool is_kprobe) 1654225466f1SSrikar Dronamraju { 1655225466f1SSrikar Dronamraju 1656225466f1SSrikar Dronamraju if (errno == ENOENT) { 1657225466f1SSrikar Dronamraju const char *config; 1658225466f1SSrikar Dronamraju 1659225466f1SSrikar Dronamraju if (!is_kprobe) 1660225466f1SSrikar Dronamraju config = "CONFIG_UPROBE_EVENTS"; 1661225466f1SSrikar Dronamraju else 1662225466f1SSrikar Dronamraju config = "CONFIG_KPROBE_EVENTS"; 1663225466f1SSrikar Dronamraju 1664225466f1SSrikar Dronamraju pr_warning("%s file does not exist - please rebuild kernel" 1665225466f1SSrikar Dronamraju " with %s.\n", file, config); 1666225466f1SSrikar Dronamraju } else 1667225466f1SSrikar Dronamraju pr_warning("Failed to open %s file: %s\n", file, 1668225466f1SSrikar Dronamraju strerror(errno)); 1669225466f1SSrikar Dronamraju } 1670225466f1SSrikar Dronamraju 1671225466f1SSrikar Dronamraju static int open_probe_events(const char *trace_file, bool readwrite, 1672225466f1SSrikar Dronamraju bool is_kprobe) 16734de189feSMasami Hiramatsu { 16744de189feSMasami Hiramatsu char buf[PATH_MAX]; 16757ca5989dSMasami Hiramatsu const char *__debugfs; 16764de189feSMasami Hiramatsu int ret; 16774de189feSMasami Hiramatsu 16787ca5989dSMasami Hiramatsu __debugfs = debugfs_find_mountpoint(); 16797ca5989dSMasami Hiramatsu if (__debugfs == NULL) { 16807ca5989dSMasami Hiramatsu pr_warning("Debugfs is not mounted.\n"); 16817ca5989dSMasami Hiramatsu return -ENOENT; 16827ca5989dSMasami Hiramatsu } 16837ca5989dSMasami Hiramatsu 1684225466f1SSrikar Dronamraju ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file); 1685146a1439SMasami Hiramatsu if (ret >= 0) { 16867ca5989dSMasami Hiramatsu pr_debug("Opening %s write=%d\n", buf, readwrite); 1687f4d7da49SMasami Hiramatsu if (readwrite && !probe_event_dry_run) 1688f4d7da49SMasami Hiramatsu ret = open(buf, O_RDWR, O_APPEND); 1689f4d7da49SMasami Hiramatsu else 1690f4d7da49SMasami Hiramatsu ret = open(buf, O_RDONLY, 0); 1691f4d7da49SMasami Hiramatsu 1692225466f1SSrikar Dronamraju if (ret < 0) 1693225466f1SSrikar Dronamraju print_warn_msg(buf, is_kprobe); 16944de189feSMasami Hiramatsu } 16954de189feSMasami Hiramatsu return ret; 16964de189feSMasami Hiramatsu } 16974de189feSMasami Hiramatsu 1698225466f1SSrikar Dronamraju static int open_kprobe_events(bool readwrite) 1699225466f1SSrikar Dronamraju { 1700225466f1SSrikar Dronamraju return open_probe_events("tracing/kprobe_events", readwrite, true); 1701225466f1SSrikar Dronamraju } 1702225466f1SSrikar Dronamraju 1703225466f1SSrikar Dronamraju static int open_uprobe_events(bool readwrite) 1704225466f1SSrikar Dronamraju { 1705225466f1SSrikar Dronamraju return open_probe_events("tracing/uprobe_events", readwrite, false); 1706225466f1SSrikar Dronamraju } 1707225466f1SSrikar Dronamraju 1708225466f1SSrikar Dronamraju /* Get raw string list of current kprobe_events or uprobe_events */ 17090e60836bSSrikar Dronamraju static struct strlist *get_probe_trace_command_rawlist(int fd) 17104de189feSMasami Hiramatsu { 17114de189feSMasami Hiramatsu int ret, idx; 17124de189feSMasami Hiramatsu FILE *fp; 17134de189feSMasami Hiramatsu char buf[MAX_CMDLEN]; 17144de189feSMasami Hiramatsu char *p; 17154de189feSMasami Hiramatsu struct strlist *sl; 17164de189feSMasami Hiramatsu 17174de189feSMasami Hiramatsu sl = strlist__new(true, NULL); 17184de189feSMasami Hiramatsu 17194de189feSMasami Hiramatsu fp = fdopen(dup(fd), "r"); 17204de189feSMasami Hiramatsu while (!feof(fp)) { 17214de189feSMasami Hiramatsu p = fgets(buf, MAX_CMDLEN, fp); 17224de189feSMasami Hiramatsu if (!p) 17234de189feSMasami Hiramatsu break; 17244de189feSMasami Hiramatsu 17254de189feSMasami Hiramatsu idx = strlen(p) - 1; 17264de189feSMasami Hiramatsu if (p[idx] == '\n') 17274de189feSMasami Hiramatsu p[idx] = '\0'; 17284de189feSMasami Hiramatsu ret = strlist__add(sl, buf); 1729146a1439SMasami Hiramatsu if (ret < 0) { 1730146a1439SMasami Hiramatsu pr_debug("strlist__add failed: %s\n", strerror(-ret)); 1731146a1439SMasami Hiramatsu strlist__delete(sl); 1732146a1439SMasami Hiramatsu return NULL; 1733146a1439SMasami Hiramatsu } 17344de189feSMasami Hiramatsu } 17354de189feSMasami Hiramatsu fclose(fp); 17364de189feSMasami Hiramatsu 17374de189feSMasami Hiramatsu return sl; 17384de189feSMasami Hiramatsu } 17394de189feSMasami Hiramatsu 1740278498d4SMasami Hiramatsu /* Show an event */ 1741146a1439SMasami Hiramatsu static int show_perf_probe_event(struct perf_probe_event *pev) 1742278498d4SMasami Hiramatsu { 17437e990a51SMasami Hiramatsu int i, ret; 1744278498d4SMasami Hiramatsu char buf[128]; 17454235b045SMasami Hiramatsu char *place; 1746278498d4SMasami Hiramatsu 17474235b045SMasami Hiramatsu /* Synthesize only event probe point */ 17484235b045SMasami Hiramatsu place = synthesize_perf_probe_point(&pev->point); 1749146a1439SMasami Hiramatsu if (!place) 1750146a1439SMasami Hiramatsu return -EINVAL; 17514235b045SMasami Hiramatsu 17524235b045SMasami Hiramatsu ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event); 17537e990a51SMasami Hiramatsu if (ret < 0) 1754146a1439SMasami Hiramatsu return ret; 1755146a1439SMasami Hiramatsu 1756fb1587d8SMasami Hiramatsu printf(" %-20s (on %s", buf, place); 1757278498d4SMasami Hiramatsu 17584235b045SMasami Hiramatsu if (pev->nargs > 0) { 1759278498d4SMasami Hiramatsu printf(" with"); 17607df2f329SMasami Hiramatsu for (i = 0; i < pev->nargs; i++) { 1761146a1439SMasami Hiramatsu ret = synthesize_perf_probe_arg(&pev->args[i], 1762146a1439SMasami Hiramatsu buf, 128); 1763146a1439SMasami Hiramatsu if (ret < 0) 1764146a1439SMasami Hiramatsu break; 17657df2f329SMasami Hiramatsu printf(" %s", buf); 17667df2f329SMasami Hiramatsu } 1767278498d4SMasami Hiramatsu } 1768278498d4SMasami Hiramatsu printf(")\n"); 17694235b045SMasami Hiramatsu free(place); 1770146a1439SMasami Hiramatsu return ret; 1771278498d4SMasami Hiramatsu } 1772278498d4SMasami Hiramatsu 1773225466f1SSrikar Dronamraju static int __show_perf_probe_events(int fd, bool is_kprobe) 17744de189feSMasami Hiramatsu { 1775225466f1SSrikar Dronamraju int ret = 0; 17760e60836bSSrikar Dronamraju struct probe_trace_event tev; 17774235b045SMasami Hiramatsu struct perf_probe_event pev; 17784de189feSMasami Hiramatsu struct strlist *rawlist; 17794de189feSMasami Hiramatsu struct str_node *ent; 17804de189feSMasami Hiramatsu 17814235b045SMasami Hiramatsu memset(&tev, 0, sizeof(tev)); 17824235b045SMasami Hiramatsu memset(&pev, 0, sizeof(pev)); 178372041334SMasami Hiramatsu 17840e60836bSSrikar Dronamraju rawlist = get_probe_trace_command_rawlist(fd); 1785146a1439SMasami Hiramatsu if (!rawlist) 1786146a1439SMasami Hiramatsu return -ENOENT; 17874de189feSMasami Hiramatsu 1788adf365f4SMasami Hiramatsu strlist__for_each(ent, rawlist) { 17890e60836bSSrikar Dronamraju ret = parse_probe_trace_command(ent->s, &tev); 1790146a1439SMasami Hiramatsu if (ret >= 0) { 1791225466f1SSrikar Dronamraju ret = convert_to_perf_probe_event(&tev, &pev, 1792225466f1SSrikar Dronamraju is_kprobe); 1793146a1439SMasami Hiramatsu if (ret >= 0) 1794146a1439SMasami Hiramatsu ret = show_perf_probe_event(&pev); 1795146a1439SMasami Hiramatsu } 17964235b045SMasami Hiramatsu clear_perf_probe_event(&pev); 17970e60836bSSrikar Dronamraju clear_probe_trace_event(&tev); 1798146a1439SMasami Hiramatsu if (ret < 0) 1799146a1439SMasami Hiramatsu break; 18004de189feSMasami Hiramatsu } 18014de189feSMasami Hiramatsu strlist__delete(rawlist); 1802146a1439SMasami Hiramatsu 1803146a1439SMasami Hiramatsu return ret; 18044de189feSMasami Hiramatsu } 18054de189feSMasami Hiramatsu 1806225466f1SSrikar Dronamraju /* List up current perf-probe events */ 1807225466f1SSrikar Dronamraju int show_perf_probe_events(void) 1808225466f1SSrikar Dronamraju { 1809225466f1SSrikar Dronamraju int fd, ret; 1810225466f1SSrikar Dronamraju 1811225466f1SSrikar Dronamraju setup_pager(); 1812225466f1SSrikar Dronamraju fd = open_kprobe_events(false); 1813225466f1SSrikar Dronamraju 1814225466f1SSrikar Dronamraju if (fd < 0) 1815225466f1SSrikar Dronamraju return fd; 1816225466f1SSrikar Dronamraju 1817*ee45b6c2SMasami Hiramatsu ret = init_symbol_maps(false); 1818225466f1SSrikar Dronamraju if (ret < 0) 1819225466f1SSrikar Dronamraju return ret; 1820225466f1SSrikar Dronamraju 1821225466f1SSrikar Dronamraju ret = __show_perf_probe_events(fd, true); 1822225466f1SSrikar Dronamraju close(fd); 1823225466f1SSrikar Dronamraju 1824225466f1SSrikar Dronamraju fd = open_uprobe_events(false); 1825225466f1SSrikar Dronamraju if (fd >= 0) { 1826225466f1SSrikar Dronamraju ret = __show_perf_probe_events(fd, false); 1827225466f1SSrikar Dronamraju close(fd); 1828225466f1SSrikar Dronamraju } 1829225466f1SSrikar Dronamraju 1830*ee45b6c2SMasami Hiramatsu exit_symbol_maps(); 1831225466f1SSrikar Dronamraju return ret; 1832225466f1SSrikar Dronamraju } 1833225466f1SSrikar Dronamraju 1834b498ce1fSMasami Hiramatsu /* Get current perf-probe event names */ 18350e60836bSSrikar Dronamraju static struct strlist *get_probe_trace_event_names(int fd, bool include_group) 1836b498ce1fSMasami Hiramatsu { 1837fa28244dSMasami Hiramatsu char buf[128]; 1838b498ce1fSMasami Hiramatsu struct strlist *sl, *rawlist; 1839b498ce1fSMasami Hiramatsu struct str_node *ent; 18400e60836bSSrikar Dronamraju struct probe_trace_event tev; 1841146a1439SMasami Hiramatsu int ret = 0; 1842b498ce1fSMasami Hiramatsu 18434235b045SMasami Hiramatsu memset(&tev, 0, sizeof(tev)); 18440e60836bSSrikar Dronamraju rawlist = get_probe_trace_command_rawlist(fd); 1845e1d2017bSMasami Hiramatsu sl = strlist__new(true, NULL); 1846adf365f4SMasami Hiramatsu strlist__for_each(ent, rawlist) { 18470e60836bSSrikar Dronamraju ret = parse_probe_trace_command(ent->s, &tev); 1848146a1439SMasami Hiramatsu if (ret < 0) 1849146a1439SMasami Hiramatsu break; 1850fa28244dSMasami Hiramatsu if (include_group) { 1851146a1439SMasami Hiramatsu ret = e_snprintf(buf, 128, "%s:%s", tev.group, 1852146a1439SMasami Hiramatsu tev.event); 1853146a1439SMasami Hiramatsu if (ret >= 0) 1854146a1439SMasami Hiramatsu ret = strlist__add(sl, buf); 1855fa28244dSMasami Hiramatsu } else 1856146a1439SMasami Hiramatsu ret = strlist__add(sl, tev.event); 18570e60836bSSrikar Dronamraju clear_probe_trace_event(&tev); 1858146a1439SMasami Hiramatsu if (ret < 0) 1859146a1439SMasami Hiramatsu break; 1860b498ce1fSMasami Hiramatsu } 1861b498ce1fSMasami Hiramatsu strlist__delete(rawlist); 1862b498ce1fSMasami Hiramatsu 1863146a1439SMasami Hiramatsu if (ret < 0) { 1864146a1439SMasami Hiramatsu strlist__delete(sl); 1865146a1439SMasami Hiramatsu return NULL; 1866146a1439SMasami Hiramatsu } 1867b498ce1fSMasami Hiramatsu return sl; 1868b498ce1fSMasami Hiramatsu } 1869b498ce1fSMasami Hiramatsu 18700e60836bSSrikar Dronamraju static int write_probe_trace_event(int fd, struct probe_trace_event *tev) 187150656eecSMasami Hiramatsu { 18726eca8cc3SFrederic Weisbecker int ret = 0; 18730e60836bSSrikar Dronamraju char *buf = synthesize_probe_trace_command(tev); 187450656eecSMasami Hiramatsu 1875146a1439SMasami Hiramatsu if (!buf) { 18760e60836bSSrikar Dronamraju pr_debug("Failed to synthesize probe trace event.\n"); 1877146a1439SMasami Hiramatsu return -EINVAL; 1878146a1439SMasami Hiramatsu } 1879146a1439SMasami Hiramatsu 1880fa28244dSMasami Hiramatsu pr_debug("Writing event: %s\n", buf); 1881f4d7da49SMasami Hiramatsu if (!probe_event_dry_run) { 188250656eecSMasami Hiramatsu ret = write(fd, buf, strlen(buf)); 188350656eecSMasami Hiramatsu if (ret <= 0) 1884146a1439SMasami Hiramatsu pr_warning("Failed to write event: %s\n", 1885146a1439SMasami Hiramatsu strerror(errno)); 188650656eecSMasami Hiramatsu } 18874235b045SMasami Hiramatsu free(buf); 1888146a1439SMasami Hiramatsu return ret; 1889f4d7da49SMasami Hiramatsu } 189050656eecSMasami Hiramatsu 1891146a1439SMasami Hiramatsu static int get_new_event_name(char *buf, size_t len, const char *base, 1892d761b08bSMasami Hiramatsu struct strlist *namelist, bool allow_suffix) 1893b498ce1fSMasami Hiramatsu { 1894b498ce1fSMasami Hiramatsu int i, ret; 189517f88fcdSMasami Hiramatsu 189617f88fcdSMasami Hiramatsu /* Try no suffix */ 189717f88fcdSMasami Hiramatsu ret = e_snprintf(buf, len, "%s", base); 1898146a1439SMasami Hiramatsu if (ret < 0) { 1899146a1439SMasami Hiramatsu pr_debug("snprintf() failed: %s\n", strerror(-ret)); 1900146a1439SMasami Hiramatsu return ret; 1901146a1439SMasami Hiramatsu } 190217f88fcdSMasami Hiramatsu if (!strlist__has_entry(namelist, buf)) 1903146a1439SMasami Hiramatsu return 0; 190417f88fcdSMasami Hiramatsu 1905d761b08bSMasami Hiramatsu if (!allow_suffix) { 1906d761b08bSMasami Hiramatsu pr_warning("Error: event \"%s\" already exists. " 1907d761b08bSMasami Hiramatsu "(Use -f to force duplicates.)\n", base); 1908146a1439SMasami Hiramatsu return -EEXIST; 1909d761b08bSMasami Hiramatsu } 1910d761b08bSMasami Hiramatsu 191117f88fcdSMasami Hiramatsu /* Try to add suffix */ 191217f88fcdSMasami Hiramatsu for (i = 1; i < MAX_EVENT_INDEX; i++) { 1913b498ce1fSMasami Hiramatsu ret = e_snprintf(buf, len, "%s_%d", base, i); 1914146a1439SMasami Hiramatsu if (ret < 0) { 1915146a1439SMasami Hiramatsu pr_debug("snprintf() failed: %s\n", strerror(-ret)); 1916146a1439SMasami Hiramatsu return ret; 1917146a1439SMasami Hiramatsu } 1918b498ce1fSMasami Hiramatsu if (!strlist__has_entry(namelist, buf)) 1919b498ce1fSMasami Hiramatsu break; 1920b498ce1fSMasami Hiramatsu } 1921146a1439SMasami Hiramatsu if (i == MAX_EVENT_INDEX) { 1922146a1439SMasami Hiramatsu pr_warning("Too many events are on the same function.\n"); 1923146a1439SMasami Hiramatsu ret = -ERANGE; 1924b498ce1fSMasami Hiramatsu } 1925b498ce1fSMasami Hiramatsu 1926146a1439SMasami Hiramatsu return ret; 1927146a1439SMasami Hiramatsu } 1928146a1439SMasami Hiramatsu 19290e60836bSSrikar Dronamraju static int __add_probe_trace_events(struct perf_probe_event *pev, 19300e60836bSSrikar Dronamraju struct probe_trace_event *tevs, 19314235b045SMasami Hiramatsu int ntevs, bool allow_suffix) 193250656eecSMasami Hiramatsu { 1933146a1439SMasami Hiramatsu int i, fd, ret; 19340e60836bSSrikar Dronamraju struct probe_trace_event *tev = NULL; 19354235b045SMasami Hiramatsu char buf[64]; 19364235b045SMasami Hiramatsu const char *event, *group; 1937b498ce1fSMasami Hiramatsu struct strlist *namelist; 193850656eecSMasami Hiramatsu 1939225466f1SSrikar Dronamraju if (pev->uprobes) 1940225466f1SSrikar Dronamraju fd = open_uprobe_events(true); 1941225466f1SSrikar Dronamraju else 1942f4d7da49SMasami Hiramatsu fd = open_kprobe_events(true); 1943225466f1SSrikar Dronamraju 1944146a1439SMasami Hiramatsu if (fd < 0) 1945146a1439SMasami Hiramatsu return fd; 1946b498ce1fSMasami Hiramatsu /* Get current event names */ 19470e60836bSSrikar Dronamraju namelist = get_probe_trace_event_names(fd, false); 1948146a1439SMasami Hiramatsu if (!namelist) { 1949146a1439SMasami Hiramatsu pr_debug("Failed to get current event list.\n"); 1950146a1439SMasami Hiramatsu return -EIO; 1951146a1439SMasami Hiramatsu } 195250656eecSMasami Hiramatsu 1953146a1439SMasami Hiramatsu ret = 0; 1954a844d1efSSrikar Dronamraju printf("Added new event%s\n", (ntevs > 1) ? "s:" : ":"); 195502b95dadSMasami Hiramatsu for (i = 0; i < ntevs; i++) { 19564235b045SMasami Hiramatsu tev = &tevs[i]; 19574235b045SMasami Hiramatsu if (pev->event) 19584235b045SMasami Hiramatsu event = pev->event; 19594235b045SMasami Hiramatsu else 19604235b045SMasami Hiramatsu if (pev->point.function) 19614235b045SMasami Hiramatsu event = pev->point.function; 19624235b045SMasami Hiramatsu else 19634235b045SMasami Hiramatsu event = tev->point.symbol; 19644235b045SMasami Hiramatsu if (pev->group) 19654235b045SMasami Hiramatsu group = pev->group; 19664235b045SMasami Hiramatsu else 19674235b045SMasami Hiramatsu group = PERFPROBE_GROUP; 19684235b045SMasami Hiramatsu 1969b498ce1fSMasami Hiramatsu /* Get an unused new event name */ 1970146a1439SMasami Hiramatsu ret = get_new_event_name(buf, 64, event, 1971146a1439SMasami Hiramatsu namelist, allow_suffix); 1972146a1439SMasami Hiramatsu if (ret < 0) 1973146a1439SMasami Hiramatsu break; 19744235b045SMasami Hiramatsu event = buf; 19754235b045SMasami Hiramatsu 197602b95dadSMasami Hiramatsu tev->event = strdup(event); 197702b95dadSMasami Hiramatsu tev->group = strdup(group); 197802b95dadSMasami Hiramatsu if (tev->event == NULL || tev->group == NULL) { 197902b95dadSMasami Hiramatsu ret = -ENOMEM; 198002b95dadSMasami Hiramatsu break; 198102b95dadSMasami Hiramatsu } 19820e60836bSSrikar Dronamraju ret = write_probe_trace_event(fd, tev); 1983146a1439SMasami Hiramatsu if (ret < 0) 1984146a1439SMasami Hiramatsu break; 1985b498ce1fSMasami Hiramatsu /* Add added event name to namelist */ 1986b498ce1fSMasami Hiramatsu strlist__add(namelist, event); 19874235b045SMasami Hiramatsu 19884235b045SMasami Hiramatsu /* Trick here - save current event/group */ 19894235b045SMasami Hiramatsu event = pev->event; 19904235b045SMasami Hiramatsu group = pev->group; 19914235b045SMasami Hiramatsu pev->event = tev->event; 19924235b045SMasami Hiramatsu pev->group = tev->group; 19934235b045SMasami Hiramatsu show_perf_probe_event(pev); 19944235b045SMasami Hiramatsu /* Trick here - restore current event/group */ 19954235b045SMasami Hiramatsu pev->event = (char *)event; 19964235b045SMasami Hiramatsu pev->group = (char *)group; 19974235b045SMasami Hiramatsu 1998d761b08bSMasami Hiramatsu /* 1999d761b08bSMasami Hiramatsu * Probes after the first probe which comes from same 2000d761b08bSMasami Hiramatsu * user input are always allowed to add suffix, because 2001d761b08bSMasami Hiramatsu * there might be several addresses corresponding to 2002d761b08bSMasami Hiramatsu * one code line. 2003d761b08bSMasami Hiramatsu */ 2004d761b08bSMasami Hiramatsu allow_suffix = true; 200550656eecSMasami Hiramatsu } 2006146a1439SMasami Hiramatsu 2007146a1439SMasami Hiramatsu if (ret >= 0) { 2008a9b495b0SMasami Hiramatsu /* Show how to use the event. */ 2009a844d1efSSrikar Dronamraju printf("\nYou can now use it in all perf tools, such as:\n\n"); 2010146a1439SMasami Hiramatsu printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 2011146a1439SMasami Hiramatsu tev->event); 2012146a1439SMasami Hiramatsu } 2013a9b495b0SMasami Hiramatsu 2014e1d2017bSMasami Hiramatsu strlist__delete(namelist); 201550656eecSMasami Hiramatsu close(fd); 2016146a1439SMasami Hiramatsu return ret; 201750656eecSMasami Hiramatsu } 2018fa28244dSMasami Hiramatsu 20190e60836bSSrikar Dronamraju static int convert_to_probe_trace_events(struct perf_probe_event *pev, 20200e60836bSSrikar Dronamraju struct probe_trace_event **tevs, 20214eced234SSrikar Dronamraju int max_tevs, const char *target) 2022e0faa8d3SMasami Hiramatsu { 2023e0faa8d3SMasami Hiramatsu struct symbol *sym; 2024fb7345bbSMasami Hiramatsu int ret, i; 20250e60836bSSrikar Dronamraju struct probe_trace_event *tev; 20264235b045SMasami Hiramatsu 2027fb7345bbSMasami Hiramatsu if (pev->uprobes && !pev->group) { 2028fb7345bbSMasami Hiramatsu /* Replace group name if not given */ 2029fb7345bbSMasami Hiramatsu ret = convert_exec_to_group(target, &pev->group); 2030fb7345bbSMasami Hiramatsu if (ret != 0) { 2031fb7345bbSMasami Hiramatsu pr_warning("Failed to make a group name.\n"); 2032fb7345bbSMasami Hiramatsu return ret; 2033fb7345bbSMasami Hiramatsu } 2034fb7345bbSMasami Hiramatsu } 2035fb7345bbSMasami Hiramatsu 20364b4da7f7SMasami Hiramatsu /* Convert perf_probe_event with debuginfo */ 20374eced234SSrikar Dronamraju ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target); 2038e334016fSMasami Hiramatsu if (ret != 0) 2039190b57fcSMasami Hiramatsu return ret; /* Found in debuginfo or got an error */ 2040e0faa8d3SMasami Hiramatsu 2041fb7345bbSMasami Hiramatsu if (pev->uprobes) { 2042fb7345bbSMasami Hiramatsu ret = convert_name_to_addr(pev, target); 2043fb7345bbSMasami Hiramatsu if (ret < 0) 2044fb7345bbSMasami Hiramatsu return ret; 2045fb7345bbSMasami Hiramatsu } 2046fb7345bbSMasami Hiramatsu 20474235b045SMasami Hiramatsu /* Allocate trace event buffer */ 20480e60836bSSrikar Dronamraju tev = *tevs = zalloc(sizeof(struct probe_trace_event)); 2049e334016fSMasami Hiramatsu if (tev == NULL) 2050e334016fSMasami Hiramatsu return -ENOMEM; 2051e0faa8d3SMasami Hiramatsu 20524235b045SMasami Hiramatsu /* Copy parameters */ 205302b95dadSMasami Hiramatsu tev->point.symbol = strdup(pev->point.function); 205402b95dadSMasami Hiramatsu if (tev->point.symbol == NULL) { 205502b95dadSMasami Hiramatsu ret = -ENOMEM; 205602b95dadSMasami Hiramatsu goto error; 205702b95dadSMasami Hiramatsu } 2058ce27a443SJovi Zhang 20594eced234SSrikar Dronamraju if (target) { 20604eced234SSrikar Dronamraju tev->point.module = strdup(target); 2061190b57fcSMasami Hiramatsu if (tev->point.module == NULL) { 2062190b57fcSMasami Hiramatsu ret = -ENOMEM; 2063190b57fcSMasami Hiramatsu goto error; 2064190b57fcSMasami Hiramatsu } 2065ce27a443SJovi Zhang } 2066ce27a443SJovi Zhang 20674235b045SMasami Hiramatsu tev->point.offset = pev->point.offset; 206804ddd04bSMasami Hiramatsu tev->point.retprobe = pev->point.retprobe; 20694235b045SMasami Hiramatsu tev->nargs = pev->nargs; 2070225466f1SSrikar Dronamraju tev->uprobes = pev->uprobes; 2071225466f1SSrikar Dronamraju 20724235b045SMasami Hiramatsu if (tev->nargs) { 20730e60836bSSrikar Dronamraju tev->args = zalloc(sizeof(struct probe_trace_arg) 20744235b045SMasami Hiramatsu * tev->nargs); 2075e334016fSMasami Hiramatsu if (tev->args == NULL) { 207602b95dadSMasami Hiramatsu ret = -ENOMEM; 207702b95dadSMasami Hiramatsu goto error; 2078e334016fSMasami Hiramatsu } 207948481938SMasami Hiramatsu for (i = 0; i < tev->nargs; i++) { 208002b95dadSMasami Hiramatsu if (pev->args[i].name) { 208102b95dadSMasami Hiramatsu tev->args[i].name = strdup(pev->args[i].name); 208202b95dadSMasami Hiramatsu if (tev->args[i].name == NULL) { 208302b95dadSMasami Hiramatsu ret = -ENOMEM; 208402b95dadSMasami Hiramatsu goto error; 208502b95dadSMasami Hiramatsu } 208602b95dadSMasami Hiramatsu } 208702b95dadSMasami Hiramatsu tev->args[i].value = strdup(pev->args[i].var); 208802b95dadSMasami Hiramatsu if (tev->args[i].value == NULL) { 208902b95dadSMasami Hiramatsu ret = -ENOMEM; 209002b95dadSMasami Hiramatsu goto error; 209102b95dadSMasami Hiramatsu } 209202b95dadSMasami Hiramatsu if (pev->args[i].type) { 209302b95dadSMasami Hiramatsu tev->args[i].type = strdup(pev->args[i].type); 209402b95dadSMasami Hiramatsu if (tev->args[i].type == NULL) { 209502b95dadSMasami Hiramatsu ret = -ENOMEM; 209602b95dadSMasami Hiramatsu goto error; 209702b95dadSMasami Hiramatsu } 209802b95dadSMasami Hiramatsu } 209948481938SMasami Hiramatsu } 2100e0faa8d3SMasami Hiramatsu } 2101e0faa8d3SMasami Hiramatsu 2102225466f1SSrikar Dronamraju if (pev->uprobes) 2103225466f1SSrikar Dronamraju return 1; 2104225466f1SSrikar Dronamraju 21054235b045SMasami Hiramatsu /* Currently just checking function name from symbol map */ 2106469b9b88SMasami Hiramatsu sym = __find_kernel_function_by_name(tev->point.symbol, NULL); 2107146a1439SMasami Hiramatsu if (!sym) { 2108146a1439SMasami Hiramatsu pr_warning("Kernel symbol \'%s\' not found.\n", 21094235b045SMasami Hiramatsu tev->point.symbol); 211002b95dadSMasami Hiramatsu ret = -ENOENT; 211102b95dadSMasami Hiramatsu goto error; 21121c1bc922SPrashanth Nageshappa } else if (tev->point.offset > sym->end - sym->start) { 21131c1bc922SPrashanth Nageshappa pr_warning("Offset specified is greater than size of %s\n", 21141c1bc922SPrashanth Nageshappa tev->point.symbol); 21151c1bc922SPrashanth Nageshappa ret = -ENOENT; 21161c1bc922SPrashanth Nageshappa goto error; 21171c1bc922SPrashanth Nageshappa 211802b95dadSMasami Hiramatsu } 211902b95dadSMasami Hiramatsu 212002b95dadSMasami Hiramatsu return 1; 212102b95dadSMasami Hiramatsu error: 21220e60836bSSrikar Dronamraju clear_probe_trace_event(tev); 2123e334016fSMasami Hiramatsu free(tev); 2124e334016fSMasami Hiramatsu *tevs = NULL; 2125e334016fSMasami Hiramatsu return ret; 21264235b045SMasami Hiramatsu } 21274235b045SMasami Hiramatsu 21284235b045SMasami Hiramatsu struct __event_package { 21294235b045SMasami Hiramatsu struct perf_probe_event *pev; 21300e60836bSSrikar Dronamraju struct probe_trace_event *tevs; 21314235b045SMasami Hiramatsu int ntevs; 21324235b045SMasami Hiramatsu }; 21334235b045SMasami Hiramatsu 2134146a1439SMasami Hiramatsu int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 21354eced234SSrikar Dronamraju int max_tevs, const char *target, bool force_add) 21364235b045SMasami Hiramatsu { 2137146a1439SMasami Hiramatsu int i, j, ret; 21384235b045SMasami Hiramatsu struct __event_package *pkgs; 21394235b045SMasami Hiramatsu 2140225466f1SSrikar Dronamraju ret = 0; 2141e334016fSMasami Hiramatsu pkgs = zalloc(sizeof(struct __event_package) * npevs); 2142225466f1SSrikar Dronamraju 2143e334016fSMasami Hiramatsu if (pkgs == NULL) 2144e334016fSMasami Hiramatsu return -ENOMEM; 21454235b045SMasami Hiramatsu 2146*ee45b6c2SMasami Hiramatsu ret = init_symbol_maps(pevs->uprobes); 2147449e5b24SMasami Hiramatsu if (ret < 0) { 2148449e5b24SMasami Hiramatsu free(pkgs); 2149146a1439SMasami Hiramatsu return ret; 2150449e5b24SMasami Hiramatsu } 21514235b045SMasami Hiramatsu 21524235b045SMasami Hiramatsu /* Loop 1: convert all events */ 21534235b045SMasami Hiramatsu for (i = 0; i < npevs; i++) { 21544235b045SMasami Hiramatsu pkgs[i].pev = &pevs[i]; 21554235b045SMasami Hiramatsu /* Convert with or without debuginfo */ 21560e60836bSSrikar Dronamraju ret = convert_to_probe_trace_events(pkgs[i].pev, 2157469b9b88SMasami Hiramatsu &pkgs[i].tevs, 2158469b9b88SMasami Hiramatsu max_tevs, 21594eced234SSrikar Dronamraju target); 2160146a1439SMasami Hiramatsu if (ret < 0) 2161146a1439SMasami Hiramatsu goto end; 2162146a1439SMasami Hiramatsu pkgs[i].ntevs = ret; 21634235b045SMasami Hiramatsu } 21644235b045SMasami Hiramatsu 21654235b045SMasami Hiramatsu /* Loop 2: add all events */ 21668635bf6eSArnaldo Carvalho de Melo for (i = 0; i < npevs; i++) { 21670e60836bSSrikar Dronamraju ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs, 21684235b045SMasami Hiramatsu pkgs[i].ntevs, force_add); 2169fbee632dSArnaldo Carvalho de Melo if (ret < 0) 2170fbee632dSArnaldo Carvalho de Melo break; 2171fbee632dSArnaldo Carvalho de Melo } 2172146a1439SMasami Hiramatsu end: 2173449e5b24SMasami Hiramatsu /* Loop 3: cleanup and free trace events */ 2174449e5b24SMasami Hiramatsu for (i = 0; i < npevs; i++) { 2175146a1439SMasami Hiramatsu for (j = 0; j < pkgs[i].ntevs; j++) 21760e60836bSSrikar Dronamraju clear_probe_trace_event(&pkgs[i].tevs[j]); 217774cf249dSArnaldo Carvalho de Melo zfree(&pkgs[i].tevs); 2178449e5b24SMasami Hiramatsu } 2179449e5b24SMasami Hiramatsu free(pkgs); 2180*ee45b6c2SMasami Hiramatsu exit_symbol_maps(); 2181146a1439SMasami Hiramatsu 2182146a1439SMasami Hiramatsu return ret; 2183e0faa8d3SMasami Hiramatsu } 2184e0faa8d3SMasami Hiramatsu 21850e60836bSSrikar Dronamraju static int __del_trace_probe_event(int fd, struct str_node *ent) 2186bbbb521bSMasami Hiramatsu { 2187bbbb521bSMasami Hiramatsu char *p; 2188bbbb521bSMasami Hiramatsu char buf[128]; 21894235b045SMasami Hiramatsu int ret; 2190bbbb521bSMasami Hiramatsu 21910e60836bSSrikar Dronamraju /* Convert from perf-probe event to trace-probe event */ 2192146a1439SMasami Hiramatsu ret = e_snprintf(buf, 128, "-:%s", ent->s); 2193146a1439SMasami Hiramatsu if (ret < 0) 2194146a1439SMasami Hiramatsu goto error; 2195146a1439SMasami Hiramatsu 2196bbbb521bSMasami Hiramatsu p = strchr(buf + 2, ':'); 2197146a1439SMasami Hiramatsu if (!p) { 2198146a1439SMasami Hiramatsu pr_debug("Internal error: %s should have ':' but not.\n", 2199146a1439SMasami Hiramatsu ent->s); 2200146a1439SMasami Hiramatsu ret = -ENOTSUP; 2201146a1439SMasami Hiramatsu goto error; 2202146a1439SMasami Hiramatsu } 2203bbbb521bSMasami Hiramatsu *p = '/'; 2204bbbb521bSMasami Hiramatsu 22054235b045SMasami Hiramatsu pr_debug("Writing event: %s\n", buf); 22064235b045SMasami Hiramatsu ret = write(fd, buf, strlen(buf)); 220744a56040SMasami Hiramatsu if (ret < 0) { 220844a56040SMasami Hiramatsu ret = -errno; 2209146a1439SMasami Hiramatsu goto error; 221044a56040SMasami Hiramatsu } 2211146a1439SMasami Hiramatsu 2212a844d1efSSrikar Dronamraju printf("Removed event: %s\n", ent->s); 2213146a1439SMasami Hiramatsu return 0; 2214146a1439SMasami Hiramatsu error: 2215146a1439SMasami Hiramatsu pr_warning("Failed to delete event: %s\n", strerror(-ret)); 2216146a1439SMasami Hiramatsu return ret; 2217bbbb521bSMasami Hiramatsu } 2218bbbb521bSMasami Hiramatsu 2219225466f1SSrikar Dronamraju static int del_trace_probe_event(int fd, const char *buf, 2220225466f1SSrikar Dronamraju struct strlist *namelist) 2221fa28244dSMasami Hiramatsu { 2222bbbb521bSMasami Hiramatsu struct str_node *ent, *n; 2223225466f1SSrikar Dronamraju int ret = -1; 2224fa28244dSMasami Hiramatsu 2225bbbb521bSMasami Hiramatsu if (strpbrk(buf, "*?")) { /* Glob-exp */ 2226bbbb521bSMasami Hiramatsu strlist__for_each_safe(ent, n, namelist) 2227bbbb521bSMasami Hiramatsu if (strglobmatch(ent->s, buf)) { 22280e60836bSSrikar Dronamraju ret = __del_trace_probe_event(fd, ent); 2229146a1439SMasami Hiramatsu if (ret < 0) 2230146a1439SMasami Hiramatsu break; 22313e340590SMasami Hiramatsu strlist__remove(namelist, ent); 2232fa28244dSMasami Hiramatsu } 2233bbbb521bSMasami Hiramatsu } else { 2234bbbb521bSMasami Hiramatsu ent = strlist__find(namelist, buf); 2235bbbb521bSMasami Hiramatsu if (ent) { 22360e60836bSSrikar Dronamraju ret = __del_trace_probe_event(fd, ent); 2237146a1439SMasami Hiramatsu if (ret >= 0) 2238bbbb521bSMasami Hiramatsu strlist__remove(namelist, ent); 2239bbbb521bSMasami Hiramatsu } 2240bbbb521bSMasami Hiramatsu } 2241146a1439SMasami Hiramatsu 2242146a1439SMasami Hiramatsu return ret; 2243bbbb521bSMasami Hiramatsu } 2244fa28244dSMasami Hiramatsu 2245146a1439SMasami Hiramatsu int del_perf_probe_events(struct strlist *dellist) 2246fa28244dSMasami Hiramatsu { 2247225466f1SSrikar Dronamraju int ret = -1, ufd = -1, kfd = -1; 2248225466f1SSrikar Dronamraju char buf[128]; 2249fa28244dSMasami Hiramatsu const char *group, *event; 2250fa28244dSMasami Hiramatsu char *p, *str; 2251fa28244dSMasami Hiramatsu struct str_node *ent; 2252225466f1SSrikar Dronamraju struct strlist *namelist = NULL, *unamelist = NULL; 2253146a1439SMasami Hiramatsu 2254fa28244dSMasami Hiramatsu /* Get current event names */ 2255225466f1SSrikar Dronamraju kfd = open_kprobe_events(true); 2256225466f1SSrikar Dronamraju if (kfd < 0) 2257225466f1SSrikar Dronamraju return kfd; 2258225466f1SSrikar Dronamraju 2259225466f1SSrikar Dronamraju namelist = get_probe_trace_event_names(kfd, true); 2260225466f1SSrikar Dronamraju ufd = open_uprobe_events(true); 2261225466f1SSrikar Dronamraju 2262225466f1SSrikar Dronamraju if (ufd >= 0) 2263225466f1SSrikar Dronamraju unamelist = get_probe_trace_event_names(ufd, true); 2264225466f1SSrikar Dronamraju 2265225466f1SSrikar Dronamraju if (namelist == NULL && unamelist == NULL) 2266225466f1SSrikar Dronamraju goto error; 2267fa28244dSMasami Hiramatsu 2268adf365f4SMasami Hiramatsu strlist__for_each(ent, dellist) { 226902b95dadSMasami Hiramatsu str = strdup(ent->s); 227002b95dadSMasami Hiramatsu if (str == NULL) { 227102b95dadSMasami Hiramatsu ret = -ENOMEM; 2272225466f1SSrikar Dronamraju goto error; 227302b95dadSMasami Hiramatsu } 2274bbbb521bSMasami Hiramatsu pr_debug("Parsing: %s\n", str); 2275fa28244dSMasami Hiramatsu p = strchr(str, ':'); 2276fa28244dSMasami Hiramatsu if (p) { 2277fa28244dSMasami Hiramatsu group = str; 2278fa28244dSMasami Hiramatsu *p = '\0'; 2279fa28244dSMasami Hiramatsu event = p + 1; 2280fa28244dSMasami Hiramatsu } else { 2281bbbb521bSMasami Hiramatsu group = "*"; 2282fa28244dSMasami Hiramatsu event = str; 2283fa28244dSMasami Hiramatsu } 2284225466f1SSrikar Dronamraju 2285225466f1SSrikar Dronamraju ret = e_snprintf(buf, 128, "%s:%s", group, event); 2286225466f1SSrikar Dronamraju if (ret < 0) { 2287225466f1SSrikar Dronamraju pr_err("Failed to copy event."); 2288fa28244dSMasami Hiramatsu free(str); 2289225466f1SSrikar Dronamraju goto error; 2290fa28244dSMasami Hiramatsu } 2291225466f1SSrikar Dronamraju 2292225466f1SSrikar Dronamraju pr_debug("Group: %s, Event: %s\n", group, event); 2293225466f1SSrikar Dronamraju 2294225466f1SSrikar Dronamraju if (namelist) 2295225466f1SSrikar Dronamraju ret = del_trace_probe_event(kfd, buf, namelist); 2296225466f1SSrikar Dronamraju 2297225466f1SSrikar Dronamraju if (unamelist && ret != 0) 2298225466f1SSrikar Dronamraju ret = del_trace_probe_event(ufd, buf, unamelist); 2299225466f1SSrikar Dronamraju 2300225466f1SSrikar Dronamraju if (ret != 0) 2301225466f1SSrikar Dronamraju pr_info("Info: Event \"%s\" does not exist.\n", buf); 2302225466f1SSrikar Dronamraju 2303225466f1SSrikar Dronamraju free(str); 2304225466f1SSrikar Dronamraju } 2305225466f1SSrikar Dronamraju 2306225466f1SSrikar Dronamraju error: 2307225466f1SSrikar Dronamraju if (kfd >= 0) { 2308fa28244dSMasami Hiramatsu strlist__delete(namelist); 2309225466f1SSrikar Dronamraju close(kfd); 2310225466f1SSrikar Dronamraju } 2311225466f1SSrikar Dronamraju 2312225466f1SSrikar Dronamraju if (ufd >= 0) { 2313225466f1SSrikar Dronamraju strlist__delete(unamelist); 2314225466f1SSrikar Dronamraju close(ufd); 2315225466f1SSrikar Dronamraju } 2316146a1439SMasami Hiramatsu 2317146a1439SMasami Hiramatsu return ret; 2318fa28244dSMasami Hiramatsu } 2319225466f1SSrikar Dronamraju 23203c42258cSMasami Hiramatsu /* TODO: don't use a global variable for filter ... */ 23213c42258cSMasami Hiramatsu static struct strfilter *available_func_filter; 2322fa28244dSMasami Hiramatsu 2323e80711caSMasami Hiramatsu /* 23243c42258cSMasami Hiramatsu * If a symbol corresponds to a function with global binding and 23253c42258cSMasami Hiramatsu * matches filter return 0. For all others return 1. 2326e80711caSMasami Hiramatsu */ 23271d037ca1SIrina Tirdea static int filter_available_functions(struct map *map __maybe_unused, 2328e80711caSMasami Hiramatsu struct symbol *sym) 2329e80711caSMasami Hiramatsu { 23303c42258cSMasami Hiramatsu if (sym->binding == STB_GLOBAL && 23313c42258cSMasami Hiramatsu strfilter__compare(available_func_filter, sym->name)) 2332e80711caSMasami Hiramatsu return 0; 23333c42258cSMasami Hiramatsu return 1; 2334e80711caSMasami Hiramatsu } 2335e80711caSMasami Hiramatsu 2336225466f1SSrikar Dronamraju static int __show_available_funcs(struct map *map) 2337e80711caSMasami Hiramatsu { 23383c42258cSMasami Hiramatsu if (map__load(map, filter_available_functions)) { 2339e80711caSMasami Hiramatsu pr_err("Failed to load map.\n"); 2340e80711caSMasami Hiramatsu return -EINVAL; 2341e80711caSMasami Hiramatsu } 2342e80711caSMasami Hiramatsu if (!dso__sorted_by_name(map->dso, map->type)) 2343e80711caSMasami Hiramatsu dso__sort_by_name(map->dso, map->type); 2344e80711caSMasami Hiramatsu 2345e80711caSMasami Hiramatsu dso__fprintf_symbols_by_name(map->dso, map->type, stdout); 2346e80711caSMasami Hiramatsu return 0; 2347e80711caSMasami Hiramatsu } 2348225466f1SSrikar Dronamraju 2349225466f1SSrikar Dronamraju static int available_kernel_funcs(const char *module) 2350225466f1SSrikar Dronamraju { 2351225466f1SSrikar Dronamraju struct map *map; 2352225466f1SSrikar Dronamraju int ret; 2353225466f1SSrikar Dronamraju 2354*ee45b6c2SMasami Hiramatsu ret = init_symbol_maps(false); 2355225466f1SSrikar Dronamraju if (ret < 0) 2356225466f1SSrikar Dronamraju return ret; 2357225466f1SSrikar Dronamraju 2358225466f1SSrikar Dronamraju map = kernel_get_module_map(module); 2359225466f1SSrikar Dronamraju if (!map) { 2360225466f1SSrikar Dronamraju pr_err("Failed to find %s map.\n", (module) ? : "kernel"); 2361225466f1SSrikar Dronamraju return -EINVAL; 2362225466f1SSrikar Dronamraju } 2363*ee45b6c2SMasami Hiramatsu ret = __show_available_funcs(map); 2364*ee45b6c2SMasami Hiramatsu exit_symbol_maps(); 2365*ee45b6c2SMasami Hiramatsu 2366*ee45b6c2SMasami Hiramatsu return ret; 2367225466f1SSrikar Dronamraju } 2368225466f1SSrikar Dronamraju 2369225466f1SSrikar Dronamraju static int available_user_funcs(const char *target) 2370225466f1SSrikar Dronamraju { 2371225466f1SSrikar Dronamraju struct map *map; 2372225466f1SSrikar Dronamraju int ret; 2373225466f1SSrikar Dronamraju 2374*ee45b6c2SMasami Hiramatsu ret = init_symbol_maps(true); 2375225466f1SSrikar Dronamraju if (ret < 0) 2376225466f1SSrikar Dronamraju return ret; 2377225466f1SSrikar Dronamraju 2378225466f1SSrikar Dronamraju map = dso__new_map(target); 2379225466f1SSrikar Dronamraju ret = __show_available_funcs(map); 2380225466f1SSrikar Dronamraju dso__delete(map->dso); 2381225466f1SSrikar Dronamraju map__delete(map); 2382*ee45b6c2SMasami Hiramatsu exit_symbol_maps(); 2383225466f1SSrikar Dronamraju return ret; 2384225466f1SSrikar Dronamraju } 2385225466f1SSrikar Dronamraju 2386225466f1SSrikar Dronamraju int show_available_funcs(const char *target, struct strfilter *_filter, 2387225466f1SSrikar Dronamraju bool user) 2388225466f1SSrikar Dronamraju { 2389225466f1SSrikar Dronamraju setup_pager(); 2390225466f1SSrikar Dronamraju available_func_filter = _filter; 2391225466f1SSrikar Dronamraju 2392225466f1SSrikar Dronamraju if (!user) 2393225466f1SSrikar Dronamraju return available_kernel_funcs(target); 2394225466f1SSrikar Dronamraju 2395225466f1SSrikar Dronamraju return available_user_funcs(target); 2396225466f1SSrikar Dronamraju } 2397225466f1SSrikar Dronamraju 2398225466f1SSrikar Dronamraju /* 2399225466f1SSrikar Dronamraju * uprobe_events only accepts address: 2400225466f1SSrikar Dronamraju * Convert function and any offset to address 2401225466f1SSrikar Dronamraju */ 2402225466f1SSrikar Dronamraju static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) 2403225466f1SSrikar Dronamraju { 2404225466f1SSrikar Dronamraju struct perf_probe_point *pp = &pev->point; 2405225466f1SSrikar Dronamraju struct symbol *sym; 2406225466f1SSrikar Dronamraju struct map *map = NULL; 24078a613d40SMasami Hiramatsu char *function = NULL; 2408225466f1SSrikar Dronamraju int ret = -EINVAL; 2409225466f1SSrikar Dronamraju unsigned long long vaddr = 0; 2410225466f1SSrikar Dronamraju 2411225466f1SSrikar Dronamraju if (!pp->function) { 2412225466f1SSrikar Dronamraju pr_warning("No function specified for uprobes"); 2413225466f1SSrikar Dronamraju goto out; 2414225466f1SSrikar Dronamraju } 2415225466f1SSrikar Dronamraju 2416225466f1SSrikar Dronamraju function = strdup(pp->function); 2417225466f1SSrikar Dronamraju if (!function) { 2418225466f1SSrikar Dronamraju pr_warning("Failed to allocate memory by strdup.\n"); 2419225466f1SSrikar Dronamraju ret = -ENOMEM; 2420225466f1SSrikar Dronamraju goto out; 2421225466f1SSrikar Dronamraju } 2422225466f1SSrikar Dronamraju 24238a613d40SMasami Hiramatsu map = dso__new_map(exec); 2424225466f1SSrikar Dronamraju if (!map) { 2425225466f1SSrikar Dronamraju pr_warning("Cannot find appropriate DSO for %s.\n", exec); 2426225466f1SSrikar Dronamraju goto out; 2427225466f1SSrikar Dronamraju } 2428225466f1SSrikar Dronamraju available_func_filter = strfilter__new(function, NULL); 2429225466f1SSrikar Dronamraju if (map__load(map, filter_available_functions)) { 2430225466f1SSrikar Dronamraju pr_err("Failed to load map.\n"); 2431225466f1SSrikar Dronamraju goto out; 2432225466f1SSrikar Dronamraju } 2433225466f1SSrikar Dronamraju 2434225466f1SSrikar Dronamraju sym = map__find_symbol_by_name(map, function, NULL); 2435225466f1SSrikar Dronamraju if (!sym) { 2436225466f1SSrikar Dronamraju pr_warning("Cannot find %s in DSO %s\n", function, exec); 2437225466f1SSrikar Dronamraju goto out; 2438225466f1SSrikar Dronamraju } 2439225466f1SSrikar Dronamraju 2440225466f1SSrikar Dronamraju if (map->start > sym->start) 2441225466f1SSrikar Dronamraju vaddr = map->start; 2442225466f1SSrikar Dronamraju vaddr += sym->start + pp->offset + map->pgoff; 2443225466f1SSrikar Dronamraju pp->offset = 0; 2444225466f1SSrikar Dronamraju 2445225466f1SSrikar Dronamraju if (!pev->event) { 2446225466f1SSrikar Dronamraju pev->event = function; 2447225466f1SSrikar Dronamraju function = NULL; 2448225466f1SSrikar Dronamraju } 2449225466f1SSrikar Dronamraju if (!pev->group) { 24501fb89448SDavid Ahern char *ptr1, *ptr2, *exec_copy; 2451225466f1SSrikar Dronamraju 2452225466f1SSrikar Dronamraju pev->group = zalloc(sizeof(char *) * 64); 24531fb89448SDavid Ahern exec_copy = strdup(exec); 24541fb89448SDavid Ahern if (!exec_copy) { 24551fb89448SDavid Ahern ret = -ENOMEM; 24561fb89448SDavid Ahern pr_warning("Failed to copy exec string.\n"); 24571fb89448SDavid Ahern goto out; 24581fb89448SDavid Ahern } 24591fb89448SDavid Ahern 24601fb89448SDavid Ahern ptr1 = strdup(basename(exec_copy)); 2461225466f1SSrikar Dronamraju if (ptr1) { 2462225466f1SSrikar Dronamraju ptr2 = strpbrk(ptr1, "-._"); 2463225466f1SSrikar Dronamraju if (ptr2) 2464225466f1SSrikar Dronamraju *ptr2 = '\0'; 2465225466f1SSrikar Dronamraju e_snprintf(pev->group, 64, "%s_%s", PERFPROBE_GROUP, 2466225466f1SSrikar Dronamraju ptr1); 2467225466f1SSrikar Dronamraju free(ptr1); 2468225466f1SSrikar Dronamraju } 24691fb89448SDavid Ahern free(exec_copy); 2470225466f1SSrikar Dronamraju } 2471225466f1SSrikar Dronamraju free(pp->function); 2472225466f1SSrikar Dronamraju pp->function = zalloc(sizeof(char *) * MAX_PROBE_ARGS); 2473225466f1SSrikar Dronamraju if (!pp->function) { 2474225466f1SSrikar Dronamraju ret = -ENOMEM; 2475225466f1SSrikar Dronamraju pr_warning("Failed to allocate memory by zalloc.\n"); 2476225466f1SSrikar Dronamraju goto out; 2477225466f1SSrikar Dronamraju } 2478225466f1SSrikar Dronamraju e_snprintf(pp->function, MAX_PROBE_ARGS, "0x%llx", vaddr); 2479225466f1SSrikar Dronamraju ret = 0; 2480225466f1SSrikar Dronamraju 2481225466f1SSrikar Dronamraju out: 2482225466f1SSrikar Dronamraju if (map) { 2483225466f1SSrikar Dronamraju dso__delete(map->dso); 2484225466f1SSrikar Dronamraju map__delete(map); 2485225466f1SSrikar Dronamraju } 2486225466f1SSrikar Dronamraju if (function) 2487225466f1SSrikar Dronamraju free(function); 2488225466f1SSrikar Dronamraju return ret; 2489225466f1SSrikar Dronamraju } 2490