diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-18 11:19:03 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-18 11:19:03 -0400 |
| commit | 4d7b4ac22fbec1a03206c6cde353f2fd6942f828 (patch) | |
| tree | 2d96a9e9c28cf6fa628a278decc00ad55a8b043b /tools/perf/builtin-probe.c | |
| parent | 3aaf51ace5975050ab43c7d4d7e439e0ae7d13d7 (diff) | |
| parent | 94f3ca95787ada3d64339a4ecb2754236ab563f6 (diff) | |
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (311 commits)
perf tools: Add mode to build without newt support
perf symbols: symbol inconsistency message should be done only at verbose=1
perf tui: Add explicit -lslang option
perf options: Type check all the remaining OPT_ variants
perf options: Type check OPT_BOOLEAN and fix the offenders
perf options: Check v type in OPT_U?INTEGER
perf options: Introduce OPT_UINTEGER
perf tui: Add workaround for slang < 2.1.4
perf record: Fix bug mismatch with -c option definition
perf options: Introduce OPT_U64
perf tui: Add help window to show key associations
perf tui: Make <- exit menus too
perf newt: Add single key shortcuts for zoom into DSO and threads
perf newt: Exit browser unconditionally when CTRL+C, q or Q is pressed
perf newt: Fix the 'A'/'a' shortcut for annotate
perf newt: Make <- exit the ui_browser
x86, perf: P4 PMU - fix counters management logic
perf newt: Make <- zoom out filters
perf report: Report number of events, not samples
perf hist: Clarify events_stats fields usage
...
Fix up trivial conflicts in kernel/fork.c and tools/perf/builtin-record.c
Diffstat (limited to 'tools/perf/builtin-probe.c')
| -rw-r--r-- | tools/perf/builtin-probe.c | 286 |
1 files changed, 95 insertions, 191 deletions
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 152d6c9b1fa4..61c6d70732c9 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
| @@ -36,13 +36,10 @@ | |||
| 36 | #include "builtin.h" | 36 | #include "builtin.h" |
| 37 | #include "util/util.h" | 37 | #include "util/util.h" |
| 38 | #include "util/strlist.h" | 38 | #include "util/strlist.h" |
| 39 | #include "util/event.h" | 39 | #include "util/symbol.h" |
| 40 | #include "util/debug.h" | 40 | #include "util/debug.h" |
| 41 | #include "util/debugfs.h" | 41 | #include "util/debugfs.h" |
| 42 | #include "util/symbol.h" | ||
| 43 | #include "util/thread.h" | ||
| 44 | #include "util/parse-options.h" | 42 | #include "util/parse-options.h" |
| 45 | #include "util/parse-events.h" /* For debugfs_path */ | ||
| 46 | #include "util/probe-finder.h" | 43 | #include "util/probe-finder.h" |
| 47 | #include "util/probe-event.h" | 44 | #include "util/probe-event.h" |
| 48 | 45 | ||
| @@ -50,103 +47,84 @@ | |||
| 50 | 47 | ||
| 51 | /* Session management structure */ | 48 | /* Session management structure */ |
| 52 | static struct { | 49 | static struct { |
| 53 | bool need_dwarf; | ||
| 54 | bool list_events; | 50 | bool list_events; |
| 55 | bool force_add; | 51 | bool force_add; |
| 56 | bool show_lines; | 52 | bool show_lines; |
| 57 | int nr_probe; | 53 | int nevents; |
| 58 | struct probe_point probes[MAX_PROBES]; | 54 | struct perf_probe_event events[MAX_PROBES]; |
| 59 | struct strlist *dellist; | 55 | struct strlist *dellist; |
| 60 | struct map_groups kmap_groups; | ||
| 61 | struct map *kmaps[MAP__NR_TYPES]; | ||
| 62 | struct line_range line_range; | 56 | struct line_range line_range; |
| 63 | } session; | 57 | int max_probe_points; |
| 58 | } params; | ||
| 64 | 59 | ||
| 65 | 60 | ||
| 66 | /* Parse an event definition. Note that any error must die. */ | 61 | /* Parse an event definition. Note that any error must die. */ |
| 67 | static void parse_probe_event(const char *str) | 62 | static int parse_probe_event(const char *str) |
| 68 | { | 63 | { |
| 69 | struct probe_point *pp = &session.probes[session.nr_probe]; | 64 | struct perf_probe_event *pev = ¶ms.events[params.nevents]; |
| 65 | int ret; | ||
| 70 | 66 | ||
| 71 | pr_debug("probe-definition(%d): %s\n", session.nr_probe, str); | 67 | pr_debug("probe-definition(%d): %s\n", params.nevents, str); |
| 72 | if (++session.nr_probe == MAX_PROBES) | 68 | if (++params.nevents == MAX_PROBES) |
| 73 | die("Too many probes (> %d) are specified.", MAX_PROBES); | 69 | die("Too many probes (> %d) are specified.", MAX_PROBES); |
| 74 | 70 | ||
| 75 | /* Parse perf-probe event into probe_point */ | 71 | /* Parse a perf-probe command into event */ |
| 76 | parse_perf_probe_event(str, pp, &session.need_dwarf); | 72 | ret = parse_perf_probe_command(str, pev); |
| 73 | pr_debug("%d arguments\n", pev->nargs); | ||
| 77 | 74 | ||
| 78 | pr_debug("%d arguments\n", pp->nr_args); | 75 | return ret; |
| 79 | } | 76 | } |
| 80 | 77 | ||
| 81 | static void parse_probe_event_argv(int argc, const char **argv) | 78 | static int parse_probe_event_argv(int argc, const char **argv) |
| 82 | { | 79 | { |
| 83 | int i, len; | 80 | int i, len, ret; |
| 84 | char *buf; | 81 | char *buf; |
| 85 | 82 | ||
| 86 | /* Bind up rest arguments */ | 83 | /* Bind up rest arguments */ |
| 87 | len = 0; | 84 | len = 0; |
| 88 | for (i = 0; i < argc; i++) | 85 | for (i = 0; i < argc; i++) |
| 89 | len += strlen(argv[i]) + 1; | 86 | len += strlen(argv[i]) + 1; |
| 90 | buf = zalloc(len + 1); | 87 | buf = xzalloc(len + 1); |
| 91 | if (!buf) | ||
| 92 | die("Failed to allocate memory for binding arguments."); | ||
| 93 | len = 0; | 88 | len = 0; |
| 94 | for (i = 0; i < argc; i++) | 89 | for (i = 0; i < argc; i++) |
| 95 | len += sprintf(&buf[len], "%s ", argv[i]); | 90 | len += sprintf(&buf[len], "%s ", argv[i]); |
| 96 | parse_probe_event(buf); | 91 | ret = parse_probe_event(buf); |
| 97 | free(buf); | 92 | free(buf); |
| 93 | return ret; | ||
| 98 | } | 94 | } |
| 99 | 95 | ||
| 100 | static int opt_add_probe_event(const struct option *opt __used, | 96 | static int opt_add_probe_event(const struct option *opt __used, |
| 101 | const char *str, int unset __used) | 97 | const char *str, int unset __used) |
| 102 | { | 98 | { |
| 103 | if (str) | 99 | if (str) |
| 104 | parse_probe_event(str); | 100 | return parse_probe_event(str); |
| 105 | return 0; | 101 | else |
| 102 | return 0; | ||
| 106 | } | 103 | } |
| 107 | 104 | ||
| 108 | static int opt_del_probe_event(const struct option *opt __used, | 105 | static int opt_del_probe_event(const struct option *opt __used, |
| 109 | const char *str, int unset __used) | 106 | const char *str, int unset __used) |
| 110 | { | 107 | { |
| 111 | if (str) { | 108 | if (str) { |
| 112 | if (!session.dellist) | 109 | if (!params.dellist) |
| 113 | session.dellist = strlist__new(true, NULL); | 110 | params.dellist = strlist__new(true, NULL); |
| 114 | strlist__add(session.dellist, str); | 111 | strlist__add(params.dellist, str); |
| 115 | } | 112 | } |
| 116 | return 0; | 113 | return 0; |
| 117 | } | 114 | } |
| 118 | 115 | ||
| 119 | /* Currently just checking function name from symbol map */ | 116 | #ifdef DWARF_SUPPORT |
| 120 | static void evaluate_probe_point(struct probe_point *pp) | ||
| 121 | { | ||
| 122 | struct symbol *sym; | ||
| 123 | sym = map__find_symbol_by_name(session.kmaps[MAP__FUNCTION], | ||
| 124 | pp->function, NULL); | ||
| 125 | if (!sym) | ||
| 126 | die("Kernel symbol \'%s\' not found - probe not added.", | ||
| 127 | pp->function); | ||
| 128 | } | ||
| 129 | |||
| 130 | #ifndef NO_DWARF_SUPPORT | ||
| 131 | static int open_vmlinux(void) | ||
| 132 | { | ||
| 133 | if (map__load(session.kmaps[MAP__FUNCTION], NULL) < 0) { | ||
| 134 | pr_debug("Failed to load kernel map.\n"); | ||
| 135 | return -EINVAL; | ||
| 136 | } | ||
| 137 | pr_debug("Try to open %s\n", | ||
| 138 | session.kmaps[MAP__FUNCTION]->dso->long_name); | ||
| 139 | return open(session.kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY); | ||
| 140 | } | ||
| 141 | |||
| 142 | static int opt_show_lines(const struct option *opt __used, | 117 | static int opt_show_lines(const struct option *opt __used, |
| 143 | const char *str, int unset __used) | 118 | const char *str, int unset __used) |
| 144 | { | 119 | { |
| 120 | int ret = 0; | ||
| 121 | |||
| 145 | if (str) | 122 | if (str) |
| 146 | parse_line_range_desc(str, &session.line_range); | 123 | ret = parse_line_range_desc(str, ¶ms.line_range); |
| 147 | INIT_LIST_HEAD(&session.line_range.line_list); | 124 | INIT_LIST_HEAD(¶ms.line_range.line_list); |
| 148 | session.show_lines = true; | 125 | params.show_lines = true; |
| 149 | return 0; | 126 | |
| 127 | return ret; | ||
| 150 | } | 128 | } |
| 151 | #endif | 129 | #endif |
| 152 | 130 | ||
| @@ -155,29 +133,25 @@ static const char * const probe_usage[] = { | |||
| 155 | "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", | 133 | "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", |
| 156 | "perf probe [<options>] --del '[GROUP:]EVENT' ...", | 134 | "perf probe [<options>] --del '[GROUP:]EVENT' ...", |
| 157 | "perf probe --list", | 135 | "perf probe --list", |
| 158 | #ifndef NO_DWARF_SUPPORT | 136 | #ifdef DWARF_SUPPORT |
| 159 | "perf probe --line 'LINEDESC'", | 137 | "perf probe --line 'LINEDESC'", |
| 160 | #endif | 138 | #endif |
| 161 | NULL | 139 | NULL |
| 162 | }; | 140 | }; |
| 163 | 141 | ||
| 164 | static const struct option options[] = { | 142 | static const struct option options[] = { |
| 165 | OPT_BOOLEAN('v', "verbose", &verbose, | 143 | OPT_INCR('v', "verbose", &verbose, |
| 166 | "be more verbose (show parsed arguments, etc)"), | 144 | "be more verbose (show parsed arguments, etc)"), |
| 167 | #ifndef NO_DWARF_SUPPORT | 145 | OPT_BOOLEAN('l', "list", ¶ms.list_events, |
| 168 | OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, | ||
| 169 | "file", "vmlinux pathname"), | ||
| 170 | #endif | ||
| 171 | OPT_BOOLEAN('l', "list", &session.list_events, | ||
| 172 | "list up current probe events"), | 146 | "list up current probe events"), |
| 173 | OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", | 147 | OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", |
| 174 | opt_del_probe_event), | 148 | opt_del_probe_event), |
| 175 | OPT_CALLBACK('a', "add", NULL, | 149 | OPT_CALLBACK('a', "add", NULL, |
| 176 | #ifdef NO_DWARF_SUPPORT | 150 | #ifdef DWARF_SUPPORT |
| 177 | "[EVENT=]FUNC[+OFF|%return] [ARG ...]", | ||
| 178 | #else | ||
| 179 | "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT" | 151 | "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT" |
| 180 | " [ARG ...]", | 152 | " [[NAME=]ARG ...]", |
| 153 | #else | ||
| 154 | "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]", | ||
| 181 | #endif | 155 | #endif |
| 182 | "probe point definition, where\n" | 156 | "probe point definition, where\n" |
| 183 | "\t\tGROUP:\tGroup name (optional)\n" | 157 | "\t\tGROUP:\tGroup name (optional)\n" |
| @@ -185,51 +159,35 @@ static const struct option options[] = { | |||
| 185 | "\t\tFUNC:\tFunction name\n" | 159 | "\t\tFUNC:\tFunction name\n" |
| 186 | "\t\tOFF:\tOffset from function entry (in byte)\n" | 160 | "\t\tOFF:\tOffset from function entry (in byte)\n" |
| 187 | "\t\t%return:\tPut the probe at function return\n" | 161 | "\t\t%return:\tPut the probe at function return\n" |
| 188 | #ifdef NO_DWARF_SUPPORT | 162 | #ifdef DWARF_SUPPORT |
| 189 | "\t\tARG:\tProbe argument (only \n" | ||
| 190 | #else | ||
| 191 | "\t\tSRC:\tSource code path\n" | 163 | "\t\tSRC:\tSource code path\n" |
| 192 | "\t\tRL:\tRelative line number from function entry.\n" | 164 | "\t\tRL:\tRelative line number from function entry.\n" |
| 193 | "\t\tAL:\tAbsolute line number in file.\n" | 165 | "\t\tAL:\tAbsolute line number in file.\n" |
| 194 | "\t\tPT:\tLazy expression of line code.\n" | 166 | "\t\tPT:\tLazy expression of line code.\n" |
| 195 | "\t\tARG:\tProbe argument (local variable name or\n" | 167 | "\t\tARG:\tProbe argument (local variable name or\n" |
| 196 | #endif | ||
| 197 | "\t\t\tkprobe-tracer argument format.)\n", | 168 | "\t\t\tkprobe-tracer argument format.)\n", |
| 169 | #else | ||
| 170 | "\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n", | ||
| 171 | #endif | ||
| 198 | opt_add_probe_event), | 172 | opt_add_probe_event), |
| 199 | OPT_BOOLEAN('f', "force", &session.force_add, "forcibly add events" | 173 | OPT_BOOLEAN('f', "force", ¶ms.force_add, "forcibly add events" |
| 200 | " with existing name"), | 174 | " with existing name"), |
| 201 | #ifndef NO_DWARF_SUPPORT | 175 | #ifdef DWARF_SUPPORT |
| 202 | OPT_CALLBACK('L', "line", NULL, | 176 | OPT_CALLBACK('L', "line", NULL, |
| 203 | "FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]", | 177 | "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]", |
| 204 | "Show source code lines.", opt_show_lines), | 178 | "Show source code lines.", opt_show_lines), |
| 179 | OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, | ||
| 180 | "file", "vmlinux pathname"), | ||
| 205 | #endif | 181 | #endif |
| 182 | OPT__DRY_RUN(&probe_event_dry_run), | ||
| 183 | OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, | ||
| 184 | "Set how many probe points can be found for a probe."), | ||
| 206 | OPT_END() | 185 | OPT_END() |
| 207 | }; | 186 | }; |
| 208 | 187 | ||
| 209 | /* Initialize symbol maps for vmlinux */ | ||
| 210 | static void init_vmlinux(void) | ||
| 211 | { | ||
| 212 | symbol_conf.sort_by_name = true; | ||
| 213 | if (symbol_conf.vmlinux_name == NULL) | ||
| 214 | symbol_conf.try_vmlinux_path = true; | ||
| 215 | else | ||
| 216 | pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name); | ||
| 217 | if (symbol__init() < 0) | ||
| 218 | die("Failed to init symbol map."); | ||
| 219 | |||
| 220 | map_groups__init(&session.kmap_groups); | ||
| 221 | if (map_groups__create_kernel_maps(&session.kmap_groups, | ||
| 222 | session.kmaps) < 0) | ||
| 223 | die("Failed to create kernel maps."); | ||
| 224 | } | ||
| 225 | |||
| 226 | int cmd_probe(int argc, const char **argv, const char *prefix __used) | 188 | int cmd_probe(int argc, const char **argv, const char *prefix __used) |
| 227 | { | 189 | { |
| 228 | int i, ret; | 190 | int ret; |
| 229 | #ifndef NO_DWARF_SUPPORT | ||
| 230 | int fd; | ||
| 231 | #endif | ||
| 232 | struct probe_point *pp; | ||
| 233 | 191 | ||
| 234 | argc = parse_options(argc, argv, options, probe_usage, | 192 | argc = parse_options(argc, argv, options, probe_usage, |
| 235 | PARSE_OPT_STOP_AT_NON_OPTION); | 193 | PARSE_OPT_STOP_AT_NON_OPTION); |
| @@ -238,123 +196,69 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
| 238 | pr_warning(" Error: '-' is not supported.\n"); | 196 | pr_warning(" Error: '-' is not supported.\n"); |
| 239 | usage_with_options(probe_usage, options); | 197 | usage_with_options(probe_usage, options); |
| 240 | } | 198 | } |
| 241 | parse_probe_event_argv(argc, argv); | 199 | ret = parse_probe_event_argv(argc, argv); |
| 200 | if (ret < 0) { | ||
| 201 | pr_err(" Error: Parse Error. (%d)\n", ret); | ||
| 202 | return ret; | ||
| 203 | } | ||
| 242 | } | 204 | } |
| 243 | 205 | ||
| 244 | if ((!session.nr_probe && !session.dellist && !session.list_events && | 206 | if (params.max_probe_points == 0) |
| 245 | !session.show_lines)) | 207 | params.max_probe_points = MAX_PROBES; |
| 246 | usage_with_options(probe_usage, options); | ||
| 247 | 208 | ||
| 248 | if (debugfs_valid_mountpoint(debugfs_path) < 0) | 209 | if ((!params.nevents && !params.dellist && !params.list_events && |
| 249 | die("Failed to find debugfs path."); | 210 | !params.show_lines)) |
| 211 | usage_with_options(probe_usage, options); | ||
| 250 | 212 | ||
| 251 | if (session.list_events) { | 213 | if (params.list_events) { |
| 252 | if (session.nr_probe != 0 || session.dellist) { | 214 | if (params.nevents != 0 || params.dellist) { |
| 253 | pr_warning(" Error: Don't use --list with" | 215 | pr_err(" Error: Don't use --list with --add/--del.\n"); |
| 254 | " --add/--del.\n"); | ||
| 255 | usage_with_options(probe_usage, options); | 216 | usage_with_options(probe_usage, options); |
| 256 | } | 217 | } |
| 257 | if (session.show_lines) { | 218 | if (params.show_lines) { |
| 258 | pr_warning(" Error: Don't use --list with --line.\n"); | 219 | pr_err(" Error: Don't use --list with --line.\n"); |
| 259 | usage_with_options(probe_usage, options); | 220 | usage_with_options(probe_usage, options); |
| 260 | } | 221 | } |
| 261 | show_perf_probe_events(); | 222 | ret = show_perf_probe_events(); |
| 262 | return 0; | 223 | if (ret < 0) |
| 224 | pr_err(" Error: Failed to show event list. (%d)\n", | ||
| 225 | ret); | ||
| 226 | return ret; | ||
| 263 | } | 227 | } |
| 264 | 228 | ||
| 265 | #ifndef NO_DWARF_SUPPORT | 229 | #ifdef DWARF_SUPPORT |
| 266 | if (session.show_lines) { | 230 | if (params.show_lines) { |
| 267 | if (session.nr_probe != 0 || session.dellist) { | 231 | if (params.nevents != 0 || params.dellist) { |
| 268 | pr_warning(" Error: Don't use --line with" | 232 | pr_warning(" Error: Don't use --line with" |
| 269 | " --add/--del.\n"); | 233 | " --add/--del.\n"); |
| 270 | usage_with_options(probe_usage, options); | 234 | usage_with_options(probe_usage, options); |
| 271 | } | 235 | } |
| 272 | init_vmlinux(); | ||
| 273 | fd = open_vmlinux(); | ||
| 274 | if (fd < 0) | ||
| 275 | die("Could not open debuginfo file."); | ||
| 276 | ret = find_line_range(fd, &session.line_range); | ||
| 277 | if (ret <= 0) | ||
| 278 | die("Source line is not found.\n"); | ||
| 279 | close(fd); | ||
| 280 | show_line_range(&session.line_range); | ||
| 281 | return 0; | ||
| 282 | } | ||
| 283 | #endif | ||
| 284 | 236 | ||
| 285 | if (session.dellist) { | 237 | ret = show_line_range(¶ms.line_range); |
| 286 | del_trace_kprobe_events(session.dellist); | 238 | if (ret < 0) |
| 287 | strlist__delete(session.dellist); | 239 | pr_err(" Error: Failed to show lines. (%d)\n", ret); |
| 288 | if (session.nr_probe == 0) | 240 | return ret; |
| 289 | return 0; | ||
| 290 | } | 241 | } |
| 242 | #endif | ||
| 291 | 243 | ||
| 292 | /* Add probes */ | 244 | if (params.dellist) { |
| 293 | init_vmlinux(); | 245 | ret = del_perf_probe_events(params.dellist); |
| 294 | 246 | strlist__delete(params.dellist); | |
| 295 | if (session.need_dwarf) | 247 | if (ret < 0) { |
| 296 | #ifdef NO_DWARF_SUPPORT | 248 | pr_err(" Error: Failed to delete events. (%d)\n", ret); |
| 297 | die("Debuginfo-analysis is not supported"); | 249 | return ret; |
| 298 | #else /* !NO_DWARF_SUPPORT */ | ||
| 299 | pr_debug("Some probes require debuginfo.\n"); | ||
| 300 | |||
| 301 | fd = open_vmlinux(); | ||
| 302 | if (fd < 0) { | ||
| 303 | if (session.need_dwarf) | ||
| 304 | die("Could not open debuginfo file."); | ||
| 305 | |||
| 306 | pr_debug("Could not open vmlinux/module file." | ||
| 307 | " Try to use symbols.\n"); | ||
| 308 | goto end_dwarf; | ||
| 309 | } | ||
| 310 | |||
| 311 | /* Searching probe points */ | ||
| 312 | for (i = 0; i < session.nr_probe; i++) { | ||
| 313 | pp = &session.probes[i]; | ||
| 314 | if (pp->found) | ||
| 315 | continue; | ||
| 316 | |||
| 317 | lseek(fd, SEEK_SET, 0); | ||
| 318 | ret = find_probe_point(fd, pp); | ||
| 319 | if (ret > 0) | ||
| 320 | continue; | ||
| 321 | if (ret == 0) { /* No error but failed to find probe point. */ | ||
| 322 | synthesize_perf_probe_point(pp); | ||
| 323 | die("Probe point '%s' not found. - probe not added.", | ||
| 324 | pp->probes[0]); | ||
| 325 | } | ||
| 326 | /* Error path */ | ||
| 327 | if (session.need_dwarf) { | ||
| 328 | if (ret == -ENOENT) | ||
| 329 | pr_warning("No dwarf info found in the vmlinux - please rebuild with CONFIG_DEBUG_INFO=y.\n"); | ||
| 330 | die("Could not analyze debuginfo."); | ||
| 331 | } | 250 | } |
| 332 | pr_debug("An error occurred in debuginfo analysis." | ||
| 333 | " Try to use symbols.\n"); | ||
| 334 | break; | ||
| 335 | } | 251 | } |
| 336 | close(fd); | ||
| 337 | |||
| 338 | end_dwarf: | ||
| 339 | #endif /* !NO_DWARF_SUPPORT */ | ||
| 340 | 252 | ||
| 341 | /* Synthesize probes without dwarf */ | 253 | if (params.nevents) { |
| 342 | for (i = 0; i < session.nr_probe; i++) { | 254 | ret = add_perf_probe_events(params.events, params.nevents, |
| 343 | pp = &session.probes[i]; | 255 | params.force_add, |
| 344 | if (pp->found) /* This probe is already found. */ | 256 | params.max_probe_points); |
| 345 | continue; | 257 | if (ret < 0) { |
| 346 | 258 | pr_err(" Error: Failed to add events. (%d)\n", ret); | |
| 347 | evaluate_probe_point(pp); | 259 | return ret; |
| 348 | ret = synthesize_trace_kprobe_event(pp); | 260 | } |
| 349 | if (ret == -E2BIG) | ||
| 350 | die("probe point definition becomes too long."); | ||
| 351 | else if (ret < 0) | ||
| 352 | die("Failed to synthesize a probe point."); | ||
| 353 | } | 261 | } |
| 354 | |||
| 355 | /* Settng up probe points */ | ||
| 356 | add_trace_kprobe_events(session.probes, session.nr_probe, | ||
| 357 | session.force_add); | ||
| 358 | return 0; | 262 | return 0; |
| 359 | } | 263 | } |
| 360 | 264 | ||
