aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2010-04-15 03:16:51 -0400
committerIngo Molnar <mingo@elte.hu>2010-04-15 03:16:51 -0400
commitb5a80b7e91d6c067339e4d81a0176a835e9bf910 (patch)
tree2b4663c3cf537af431c43037e681b0d70e5b45af /tools/perf/util
parent84b13fd596522db47f9545d5124c30cc00dfdf5a (diff)
parentf6c903f5856ffa75ae19dcee4dbb5093e320d45c (diff)
Merge branch 'perf' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/hist.c28
-rw-r--r--tools/perf/util/probe-event.c898
-rw-r--r--tools/perf/util/probe-event.h33
-rw-r--r--tools/perf/util/probe-finder.c753
-rw-r--r--tools/perf/util/probe-finder.h1
-rw-r--r--tools/perf/util/sort.c42
-rw-r--r--tools/perf/util/sort.h12
7 files changed, 1240 insertions, 527 deletions
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 18cf8b321608..9c2b8743cef6 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -68,7 +68,7 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
68 int64_t cmp = 0; 68 int64_t cmp = 0;
69 69
70 list_for_each_entry(se, &hist_entry__sort_list, list) { 70 list_for_each_entry(se, &hist_entry__sort_list, list) {
71 cmp = se->cmp(left, right); 71 cmp = se->se_cmp(left, right);
72 if (cmp) 72 if (cmp)
73 break; 73 break;
74 } 74 }
@@ -85,7 +85,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
85 list_for_each_entry(se, &hist_entry__sort_list, list) { 85 list_for_each_entry(se, &hist_entry__sort_list, list) {
86 int64_t (*f)(struct hist_entry *, struct hist_entry *); 86 int64_t (*f)(struct hist_entry *, struct hist_entry *);
87 87
88 f = se->collapse ?: se->cmp; 88 f = se->se_collapse ?: se->se_cmp;
89 89
90 cmp = f(left, right); 90 cmp = f(left, right);
91 if (cmp) 91 if (cmp)
@@ -536,8 +536,8 @@ int hist_entry__snprintf(struct hist_entry *self,
536 continue; 536 continue;
537 537
538 ret += snprintf(s + ret, size - ret, "%s", sep ?: " "); 538 ret += snprintf(s + ret, size - ret, "%s", sep ?: " ");
539 ret += se->snprintf(self, s + ret, size - ret, 539 ret += se->se_snprintf(self, s + ret, size - ret,
540 se->width ? *se->width : 0); 540 se->se_width ? *se->se_width : 0);
541 } 541 }
542 542
543 return ret; 543 return ret;
@@ -564,7 +564,7 @@ static size_t hist_entry__fprintf_callchain(struct hist_entry *self, FILE *fp,
564 if (sort__first_dimension == SORT_COMM) { 564 if (sort__first_dimension == SORT_COMM) {
565 struct sort_entry *se = list_first_entry(&hist_entry__sort_list, 565 struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
566 typeof(*se), list); 566 typeof(*se), list);
567 left_margin = se->width ? *se->width : 0; 567 left_margin = se->se_width ? *se->se_width : 0;
568 left_margin -= thread__comm_len(self->thread); 568 left_margin -= thread__comm_len(self->thread);
569 } 569 }
570 570
@@ -615,22 +615,22 @@ size_t perf_session__fprintf_hists(struct rb_root *hists,
615 if (se->elide) 615 if (se->elide)
616 continue; 616 continue;
617 if (sep) { 617 if (sep) {
618 fprintf(fp, "%c%s", *sep, se->header); 618 fprintf(fp, "%c%s", *sep, se->se_header);
619 continue; 619 continue;
620 } 620 }
621 width = strlen(se->header); 621 width = strlen(se->se_header);
622 if (se->width) { 622 if (se->se_width) {
623 if (symbol_conf.col_width_list_str) { 623 if (symbol_conf.col_width_list_str) {
624 if (col_width) { 624 if (col_width) {
625 *se->width = atoi(col_width); 625 *se->se_width = atoi(col_width);
626 col_width = strchr(col_width, ','); 626 col_width = strchr(col_width, ',');
627 if (col_width) 627 if (col_width)
628 ++col_width; 628 ++col_width;
629 } 629 }
630 } 630 }
631 width = *se->width = max(*se->width, width); 631 width = *se->se_width = max(*se->se_width, width);
632 } 632 }
633 fprintf(fp, " %*s", width, se->header); 633 fprintf(fp, " %*s", width, se->se_header);
634 } 634 }
635 fprintf(fp, "\n"); 635 fprintf(fp, "\n");
636 636
@@ -652,10 +652,10 @@ size_t perf_session__fprintf_hists(struct rb_root *hists,
652 continue; 652 continue;
653 653
654 fprintf(fp, " "); 654 fprintf(fp, " ");
655 if (se->width) 655 if (se->se_width)
656 width = *se->width; 656 width = *se->se_width;
657 else 657 else
658 width = strlen(se->header); 658 width = strlen(se->se_header);
659 for (i = 0; i < width; i++) 659 for (i = 0; i < width; i++)
660 fprintf(fp, "."); 660 fprintf(fp, ".");
661 } 661 }
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 3fc0be741b8e..5bf8ab034466 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -42,8 +42,8 @@
42#include "color.h" 42#include "color.h"
43#include "symbol.h" 43#include "symbol.h"
44#include "thread.h" 44#include "thread.h"
45#include "debugfs.h"
45#include "trace-event.h" /* For __unused */ 46#include "trace-event.h" /* For __unused */
46#include "parse-events.h" /* For debugfs_path */
47#include "probe-event.h" 47#include "probe-event.h"
48#include "probe-finder.h" 48#include "probe-finder.h"
49 49
@@ -53,7 +53,7 @@
53 53
54bool probe_event_dry_run; /* Dry run flag */ 54bool probe_event_dry_run; /* Dry run flag */
55 55
56#define semantic_error(msg ...) die("Semantic error :" msg) 56#define semantic_error(msg ...) pr_err("Semantic error :" msg)
57 57
58/* If there is no space to write, returns -E2BIG. */ 58/* If there is no space to write, returns -E2BIG. */
59static int e_snprintf(char *str, size_t size, const char *format, ...) 59static int e_snprintf(char *str, size_t size, const char *format, ...)
@@ -76,19 +76,30 @@ static struct map_groups kmap_groups;
76static struct map *kmaps[MAP__NR_TYPES]; 76static struct map *kmaps[MAP__NR_TYPES];
77 77
78/* Initialize symbol maps and path of vmlinux */ 78/* Initialize symbol maps and path of vmlinux */
79static void init_vmlinux(void) 79static int init_vmlinux(void)
80{ 80{
81 int ret;
82
81 symbol_conf.sort_by_name = true; 83 symbol_conf.sort_by_name = true;
82 if (symbol_conf.vmlinux_name == NULL) 84 if (symbol_conf.vmlinux_name == NULL)
83 symbol_conf.try_vmlinux_path = true; 85 symbol_conf.try_vmlinux_path = true;
84 else 86 else
85 pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name); 87 pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
86 if (symbol__init() < 0) 88 ret = symbol__init();
87 die("Failed to init symbol map."); 89 if (ret < 0) {
90 pr_debug("Failed to init symbol map.\n");
91 goto out;
92 }
88 93
89 map_groups__init(&kmap_groups); 94 map_groups__init(&kmap_groups);
90 if (map_groups__create_kernel_maps(&kmap_groups, kmaps) < 0) 95 ret = map_groups__create_kernel_maps(&kmap_groups, kmaps);
91 die("Failed to create kernel maps."); 96 if (ret < 0)
97 pr_debug("Failed to create kernel maps.\n");
98
99out:
100 if (ret < 0)
101 pr_warning("Failed to init vmlinux path.\n");
102 return ret;
92} 103}
93 104
94#ifdef DWARF_SUPPORT 105#ifdef DWARF_SUPPORT
@@ -102,24 +113,34 @@ static int open_vmlinux(void)
102 return open(kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY); 113 return open(kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY);
103} 114}
104 115
105static void convert_to_perf_probe_point(struct kprobe_trace_point *tp, 116/* Convert trace point to probe point with debuginfo */
106 struct perf_probe_point *pp) 117static int convert_to_perf_probe_point(struct kprobe_trace_point *tp,
118 struct perf_probe_point *pp)
107{ 119{
108 struct symbol *sym; 120 struct symbol *sym;
109 int fd, ret = 0; 121 int fd, ret = -ENOENT;
110 122
111 sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], 123 sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION],
112 tp->symbol, NULL); 124 tp->symbol, NULL);
113 if (sym) { 125 if (sym) {
114 fd = open_vmlinux(); 126 fd = open_vmlinux();
115 ret = find_perf_probe_point(fd, sym->start + tp->offset, pp); 127 if (fd >= 0) {
116 close(fd); 128 ret = find_perf_probe_point(fd,
129 sym->start + tp->offset, pp);
130 close(fd);
131 }
117 } 132 }
118 if (ret <= 0) { 133 if (ret <= 0) {
119 pp->function = xstrdup(tp->symbol); 134 pr_debug("Failed to find corresponding probes from "
135 "debuginfo. Use kprobe event information.\n");
136 pp->function = strdup(tp->symbol);
137 if (pp->function == NULL)
138 return -ENOMEM;
120 pp->offset = tp->offset; 139 pp->offset = tp->offset;
121 } 140 }
122 pp->retprobe = tp->retprobe; 141 pp->retprobe = tp->retprobe;
142
143 return 0;
123} 144}
124 145
125/* Try to find perf_probe_event with debuginfo */ 146/* Try to find perf_probe_event with debuginfo */
@@ -131,9 +152,10 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
131 152
132 fd = open_vmlinux(); 153 fd = open_vmlinux();
133 if (fd < 0) { 154 if (fd < 0) {
134 if (need_dwarf) 155 if (need_dwarf) {
135 die("Could not open debuginfo file."); 156 pr_warning("Failed to open debuginfo file.\n");
136 157 return fd;
158 }
137 pr_debug("Could not open vmlinux. Try to use symbols.\n"); 159 pr_debug("Could not open vmlinux. Try to use symbols.\n");
138 return 0; 160 return 0;
139 } 161 }
@@ -142,30 +164,32 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
142 ntevs = find_kprobe_trace_events(fd, pev, tevs); 164 ntevs = find_kprobe_trace_events(fd, pev, tevs);
143 close(fd); 165 close(fd);
144 166
145 if (ntevs > 0) /* Succeeded to find trace events */ 167 if (ntevs > 0) { /* Succeeded to find trace events */
168 pr_debug("find %d kprobe_trace_events.\n", ntevs);
146 return ntevs; 169 return ntevs;
170 }
147 171
148 if (ntevs == 0) /* No error but failed to find probe point. */ 172 if (ntevs == 0) { /* No error but failed to find probe point. */
149 die("Probe point '%s' not found. - probe not added.", 173 pr_warning("Probe point '%s' not found.\n",
150 synthesize_perf_probe_point(&pev->point)); 174 synthesize_perf_probe_point(&pev->point));
151 175 return -ENOENT;
152 /* Error path */ 176 }
177 /* Error path : ntevs < 0 */
153 if (need_dwarf) { 178 if (need_dwarf) {
154 if (ntevs == -ENOENT) 179 if (ntevs == -EBADF)
155 pr_warning("No dwarf info found in the vmlinux - " 180 pr_warning("No dwarf info found in the vmlinux - "
156 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 181 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
157 die("Could not analyze debuginfo."); 182 return ntevs;
158 } 183 }
159 pr_debug("An error occurred in debuginfo analysis." 184 pr_debug("An error occurred in debuginfo analysis."
160 " Try to use symbols.\n"); 185 " Try to use symbols.\n");
161 return 0; 186 return 0;
162
163} 187}
164 188
165#define LINEBUF_SIZE 256 189#define LINEBUF_SIZE 256
166#define NR_ADDITIONAL_LINES 2 190#define NR_ADDITIONAL_LINES 2
167 191
168static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num) 192static int show_one_line(FILE *fp, int l, bool skip, bool show_num)
169{ 193{
170 char buf[LINEBUF_SIZE]; 194 char buf[LINEBUF_SIZE];
171 const char *color = PERF_COLOR_BLUE; 195 const char *color = PERF_COLOR_BLUE;
@@ -174,7 +198,7 @@ static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num)
174 goto error; 198 goto error;
175 if (!skip) { 199 if (!skip) {
176 if (show_num) 200 if (show_num)
177 fprintf(stdout, "%7u %s", l, buf); 201 fprintf(stdout, "%7d %s", l, buf);
178 else 202 else
179 color_fprintf(stdout, color, " %s", buf); 203 color_fprintf(stdout, color, " %s", buf);
180 } 204 }
@@ -190,34 +214,48 @@ static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num)
190 color_fprintf(stdout, color, "%s", buf); 214 color_fprintf(stdout, color, "%s", buf);
191 } 215 }
192 } 216 }
193 return; 217
218 return 0;
194error: 219error:
195 if (feof(fp)) 220 if (feof(fp))
196 die("Source file is shorter than expected."); 221 pr_warning("Source file is shorter than expected.\n");
197 else 222 else
198 die("File read error: %s", strerror(errno)); 223 pr_warning("File read error: %s\n", strerror(errno));
224
225 return -1;
199} 226}
200 227
201/* 228/*
202 * Show line-range always requires debuginfo to find source file and 229 * Show line-range always requires debuginfo to find source file and
203 * line number. 230 * line number.
204 */ 231 */
205void show_line_range(struct line_range *lr) 232int show_line_range(struct line_range *lr)
206{ 233{
207 unsigned int l = 1; 234 int l = 1;
208 struct line_node *ln; 235 struct line_node *ln;
209 FILE *fp; 236 FILE *fp;
210 int fd, ret; 237 int fd, ret;
211 238
212 /* Search a line range */ 239 /* Search a line range */
213 init_vmlinux(); 240 ret = init_vmlinux();
241 if (ret < 0)
242 return ret;
243
214 fd = open_vmlinux(); 244 fd = open_vmlinux();
215 if (fd < 0) 245 if (fd < 0) {
216 die("Could not open debuginfo file."); 246 pr_warning("Failed to open debuginfo file.\n");
247 return fd;
248 }
249
217 ret = find_line_range(fd, lr); 250 ret = find_line_range(fd, lr);
218 if (ret <= 0)
219 die("Source line is not found.\n");
220 close(fd); 251 close(fd);
252 if (ret == 0) {
253 pr_warning("Specified source line is not found.\n");
254 return -ENOENT;
255 } else if (ret < 0) {
256 pr_warning("Debuginfo analysis failed. (%d)\n", ret);
257 return ret;
258 }
221 259
222 setup_pager(); 260 setup_pager();
223 261
@@ -228,52 +266,70 @@ void show_line_range(struct line_range *lr)
228 fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); 266 fprintf(stdout, "<%s:%d>\n", lr->file, lr->start);
229 267
230 fp = fopen(lr->path, "r"); 268 fp = fopen(lr->path, "r");
231 if (fp == NULL) 269 if (fp == NULL) {
232 die("Failed to open %s: %s", lr->path, strerror(errno)); 270 pr_warning("Failed to open %s: %s\n", lr->path,
271 strerror(errno));
272 return -errno;
273 }
233 /* Skip to starting line number */ 274 /* Skip to starting line number */
234 while (l < lr->start) 275 while (l < lr->start && ret >= 0)
235 show_one_line(fp, l++, true, false); 276 ret = show_one_line(fp, l++, true, false);
277 if (ret < 0)
278 goto end;
236 279
237 list_for_each_entry(ln, &lr->line_list, list) { 280 list_for_each_entry(ln, &lr->line_list, list) {
238 while (ln->line > l) 281 while (ln->line > l && ret >= 0)
239 show_one_line(fp, (l++) - lr->offset, false, false); 282 ret = show_one_line(fp, (l++) - lr->offset,
240 show_one_line(fp, (l++) - lr->offset, false, true); 283 false, false);
284 if (ret >= 0)
285 ret = show_one_line(fp, (l++) - lr->offset,
286 false, true);
287 if (ret < 0)
288 goto end;
241 } 289 }
242 290
243 if (lr->end == INT_MAX) 291 if (lr->end == INT_MAX)
244 lr->end = l + NR_ADDITIONAL_LINES; 292 lr->end = l + NR_ADDITIONAL_LINES;
245 while (l < lr->end && !feof(fp)) 293 while (l <= lr->end && !feof(fp) && ret >= 0)
246 show_one_line(fp, (l++) - lr->offset, false, false); 294 ret = show_one_line(fp, (l++) - lr->offset, false, false);
247 295end:
248 fclose(fp); 296 fclose(fp);
297 return ret;
249} 298}
250 299
251#else /* !DWARF_SUPPORT */ 300#else /* !DWARF_SUPPORT */
252 301
253static void convert_to_perf_probe_point(struct kprobe_trace_point *tp, 302static int convert_to_perf_probe_point(struct kprobe_trace_point *tp,
254 struct perf_probe_point *pp) 303 struct perf_probe_point *pp)
255{ 304{
256 pp->function = xstrdup(tp->symbol); 305 pp->function = strdup(tp->symbol);
306 if (pp->function == NULL)
307 return -ENOMEM;
257 pp->offset = tp->offset; 308 pp->offset = tp->offset;
258 pp->retprobe = tp->retprobe; 309 pp->retprobe = tp->retprobe;
310
311 return 0;
259} 312}
260 313
261static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, 314static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
262 struct kprobe_trace_event **tevs __unused) 315 struct kprobe_trace_event **tevs __unused)
263{ 316{
264 if (perf_probe_event_need_dwarf(pev)) 317 if (perf_probe_event_need_dwarf(pev)) {
265 die("Debuginfo-analysis is not supported"); 318 pr_warning("Debuginfo-analysis is not supported.\n");
319 return -ENOSYS;
320 }
266 return 0; 321 return 0;
267} 322}
268 323
269void show_line_range(struct line_range *lr __unused) 324int show_line_range(struct line_range *lr __unused)
270{ 325{
271 die("Debuginfo-analysis is not supported"); 326 pr_warning("Debuginfo-analysis is not supported.\n");
327 return -ENOSYS;
272} 328}
273 329
274#endif 330#endif
275 331
276void parse_line_range_desc(const char *arg, struct line_range *lr) 332int parse_line_range_desc(const char *arg, struct line_range *lr)
277{ 333{
278 const char *ptr; 334 const char *ptr;
279 char *tmp; 335 char *tmp;
@@ -284,29 +340,45 @@ void parse_line_range_desc(const char *arg, struct line_range *lr)
284 */ 340 */
285 ptr = strchr(arg, ':'); 341 ptr = strchr(arg, ':');
286 if (ptr) { 342 if (ptr) {
287 lr->start = (unsigned int)strtoul(ptr + 1, &tmp, 0); 343 lr->start = (int)strtoul(ptr + 1, &tmp, 0);
288 if (*tmp == '+') 344 if (*tmp == '+') {
289 lr->end = lr->start + (unsigned int)strtoul(tmp + 1, 345 lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0);
290 &tmp, 0); 346 lr->end--; /*
291 else if (*tmp == '-') 347 * Adjust the number of lines here.
292 lr->end = (unsigned int)strtoul(tmp + 1, &tmp, 0); 348 * If the number of lines == 1, the
349 * the end of line should be equal to
350 * the start of line.
351 */
352 } else if (*tmp == '-')
353 lr->end = (int)strtoul(tmp + 1, &tmp, 0);
293 else 354 else
294 lr->end = 0; 355 lr->end = INT_MAX;
295 pr_debug("Line range is %u to %u\n", lr->start, lr->end); 356 pr_debug("Line range is %d to %d\n", lr->start, lr->end);
296 if (lr->end && lr->start > lr->end) 357 if (lr->start > lr->end) {
297 semantic_error("Start line must be smaller" 358 semantic_error("Start line must be smaller"
298 " than end line."); 359 " than end line.\n");
299 if (*tmp != '\0') 360 return -EINVAL;
300 semantic_error("Tailing with invalid character '%d'.", 361 }
362 if (*tmp != '\0') {
363 semantic_error("Tailing with invalid character '%d'.\n",
301 *tmp); 364 *tmp);
302 tmp = xstrndup(arg, (ptr - arg)); 365 return -EINVAL;
303 } else 366 }
304 tmp = xstrdup(arg); 367 tmp = strndup(arg, (ptr - arg));
368 } else {
369 tmp = strdup(arg);
370 lr->end = INT_MAX;
371 }
372
373 if (tmp == NULL)
374 return -ENOMEM;
305 375
306 if (strchr(tmp, '.')) 376 if (strchr(tmp, '.'))
307 lr->file = tmp; 377 lr->file = tmp;
308 else 378 else
309 lr->function = tmp; 379 lr->function = tmp;
380
381 return 0;
310} 382}
311 383
312/* Check the name is good for event/group */ 384/* Check the name is good for event/group */
@@ -322,7 +394,7 @@ static bool check_event_name(const char *name)
322} 394}
323 395
324/* Parse probepoint definition. */ 396/* Parse probepoint definition. */
325static void parse_perf_probe_point(char *arg, struct perf_probe_event *pev) 397static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
326{ 398{
327 struct perf_probe_point *pp = &pev->point; 399 struct perf_probe_point *pp = &pev->point;
328 char *ptr, *tmp; 400 char *ptr, *tmp;
@@ -339,13 +411,18 @@ static void parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
339 if (ptr && *ptr == '=') { /* Event name */ 411 if (ptr && *ptr == '=') { /* Event name */
340 *ptr = '\0'; 412 *ptr = '\0';
341 tmp = ptr + 1; 413 tmp = ptr + 1;
342 ptr = strchr(arg, ':'); 414 if (strchr(arg, ':')) {
343 if (ptr) /* Group name is not supported yet. */ 415 semantic_error("Group name is not supported yet.\n");
344 semantic_error("Group name is not supported yet."); 416 return -ENOTSUP;
345 if (!check_event_name(arg)) 417 }
418 if (!check_event_name(arg)) {
346 semantic_error("%s is bad for event name -it must " 419 semantic_error("%s is bad for event name -it must "
347 "follow C symbol-naming rule.", arg); 420 "follow C symbol-naming rule.\n", arg);
348 pev->event = xstrdup(arg); 421 return -EINVAL;
422 }
423 pev->event = strdup(arg);
424 if (pev->event == NULL)
425 return -ENOMEM;
349 pev->group = NULL; 426 pev->group = NULL;
350 arg = tmp; 427 arg = tmp;
351 } 428 }
@@ -356,18 +433,24 @@ static void parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
356 *ptr++ = '\0'; 433 *ptr++ = '\0';
357 } 434 }
358 435
436 tmp = strdup(arg);
437 if (tmp == NULL)
438 return -ENOMEM;
439
359 /* Check arg is function or file and copy it */ 440 /* Check arg is function or file and copy it */
360 if (strchr(arg, '.')) /* File */ 441 if (strchr(tmp, '.')) /* File */
361 pp->file = xstrdup(arg); 442 pp->file = tmp;
362 else /* Function */ 443 else /* Function */
363 pp->function = xstrdup(arg); 444 pp->function = tmp;
364 445
365 /* Parse other options */ 446 /* Parse other options */
366 while (ptr) { 447 while (ptr) {
367 arg = ptr; 448 arg = ptr;
368 c = nc; 449 c = nc;
369 if (c == ';') { /* Lazy pattern must be the last part */ 450 if (c == ';') { /* Lazy pattern must be the last part */
370 pp->lazy_line = xstrdup(arg); 451 pp->lazy_line = strdup(arg);
452 if (pp->lazy_line == NULL)
453 return -ENOMEM;
371 break; 454 break;
372 } 455 }
373 ptr = strpbrk(arg, ";:+@%"); 456 ptr = strpbrk(arg, ";:+@%");
@@ -378,131 +461,211 @@ static void parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
378 switch (c) { 461 switch (c) {
379 case ':': /* Line number */ 462 case ':': /* Line number */
380 pp->line = strtoul(arg, &tmp, 0); 463 pp->line = strtoul(arg, &tmp, 0);
381 if (*tmp != '\0') 464 if (*tmp != '\0') {
382 semantic_error("There is non-digit char" 465 semantic_error("There is non-digit char"
383 " in line number."); 466 " in line number.\n");
467 return -EINVAL;
468 }
384 break; 469 break;
385 case '+': /* Byte offset from a symbol */ 470 case '+': /* Byte offset from a symbol */
386 pp->offset = strtoul(arg, &tmp, 0); 471 pp->offset = strtoul(arg, &tmp, 0);
387 if (*tmp != '\0') 472 if (*tmp != '\0') {
388 semantic_error("There is non-digit character" 473 semantic_error("There is non-digit character"
389 " in offset."); 474 " in offset.\n");
475 return -EINVAL;
476 }
390 break; 477 break;
391 case '@': /* File name */ 478 case '@': /* File name */
392 if (pp->file) 479 if (pp->file) {
393 semantic_error("SRC@SRC is not allowed."); 480 semantic_error("SRC@SRC is not allowed.\n");
394 pp->file = xstrdup(arg); 481 return -EINVAL;
482 }
483 pp->file = strdup(arg);
484 if (pp->file == NULL)
485 return -ENOMEM;
395 break; 486 break;
396 case '%': /* Probe places */ 487 case '%': /* Probe places */
397 if (strcmp(arg, "return") == 0) { 488 if (strcmp(arg, "return") == 0) {
398 pp->retprobe = 1; 489 pp->retprobe = 1;
399 } else /* Others not supported yet */ 490 } else { /* Others not supported yet */
400 semantic_error("%%%s is not supported.", arg); 491 semantic_error("%%%s is not supported.\n", arg);
492 return -ENOTSUP;
493 }
401 break; 494 break;
402 default: 495 default: /* Buggy case */
403 DIE_IF("Program has a bug."); 496 pr_err("This program has a bug at %s:%d.\n",
497 __FILE__, __LINE__);
498 return -ENOTSUP;
404 break; 499 break;
405 } 500 }
406 } 501 }
407 502
408 /* Exclusion check */ 503 /* Exclusion check */
409 if (pp->lazy_line && pp->line) 504 if (pp->lazy_line && pp->line) {
410 semantic_error("Lazy pattern can't be used with line number."); 505 semantic_error("Lazy pattern can't be used with line number.");
506 return -EINVAL;
507 }
411 508
412 if (pp->lazy_line && pp->offset) 509 if (pp->lazy_line && pp->offset) {
413 semantic_error("Lazy pattern can't be used with offset."); 510 semantic_error("Lazy pattern can't be used with offset.");
511 return -EINVAL;
512 }
414 513
415 if (pp->line && pp->offset) 514 if (pp->line && pp->offset) {
416 semantic_error("Offset can't be used with line number."); 515 semantic_error("Offset can't be used with line number.");
516 return -EINVAL;
517 }
417 518
418 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) 519 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
419 semantic_error("File always requires line number or " 520 semantic_error("File always requires line number or "
420 "lazy pattern."); 521 "lazy pattern.");
522 return -EINVAL;
523 }
421 524
422 if (pp->offset && !pp->function) 525 if (pp->offset && !pp->function) {
423 semantic_error("Offset requires an entry function."); 526 semantic_error("Offset requires an entry function.");
527 return -EINVAL;
528 }
424 529
425 if (pp->retprobe && !pp->function) 530 if (pp->retprobe && !pp->function) {
426 semantic_error("Return probe requires an entry function."); 531 semantic_error("Return probe requires an entry function.");
532 return -EINVAL;
533 }
427 534
428 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) 535 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
429 semantic_error("Offset/Line/Lazy pattern can't be used with " 536 semantic_error("Offset/Line/Lazy pattern can't be used with "
430 "return probe."); 537 "return probe.");
538 return -EINVAL;
539 }
431 540
432 pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n", 541 pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n",
433 pp->function, pp->file, pp->line, pp->offset, pp->retprobe, 542 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
434 pp->lazy_line); 543 pp->lazy_line);
544 return 0;
435} 545}
436 546
437/* Parse perf-probe event argument */ 547/* Parse perf-probe event argument */
438static void parse_perf_probe_arg(const char *str, struct perf_probe_arg *arg) 548static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
439{ 549{
440 const char *tmp; 550 char *tmp;
441 struct perf_probe_arg_field **fieldp; 551 struct perf_probe_arg_field **fieldp;
442 552
443 pr_debug("parsing arg: %s into ", str); 553 pr_debug("parsing arg: %s into ", str);
444 554
555 tmp = strchr(str, '=');
556 if (tmp) {
557 arg->name = strndup(str, tmp - str);
558 if (arg->name == NULL)
559 return -ENOMEM;
560 pr_debug("name:%s ", arg->name);
561 str = tmp + 1;
562 }
563
564 tmp = strchr(str, ':');
565 if (tmp) { /* Type setting */
566 *tmp = '\0';
567 arg->type = strdup(tmp + 1);
568 if (arg->type == NULL)
569 return -ENOMEM;
570 pr_debug("type:%s ", arg->type);
571 }
572
445 tmp = strpbrk(str, "-."); 573 tmp = strpbrk(str, "-.");
446 if (!is_c_varname(str) || !tmp) { 574 if (!is_c_varname(str) || !tmp) {
447 /* A variable, register, symbol or special value */ 575 /* A variable, register, symbol or special value */
448 arg->name = xstrdup(str); 576 arg->var = strdup(str);
449 pr_debug("%s\n", arg->name); 577 if (arg->var == NULL)
450 return; 578 return -ENOMEM;
579 pr_debug("%s\n", arg->var);
580 return 0;
451 } 581 }
452 582
453 /* Structure fields */ 583 /* Structure fields */
454 arg->name = xstrndup(str, tmp - str); 584 arg->var = strndup(str, tmp - str);
455 pr_debug("%s, ", arg->name); 585 if (arg->var == NULL)
586 return -ENOMEM;
587 pr_debug("%s, ", arg->var);
456 fieldp = &arg->field; 588 fieldp = &arg->field;
457 589
458 do { 590 do {
459 *fieldp = xzalloc(sizeof(struct perf_probe_arg_field)); 591 *fieldp = zalloc(sizeof(struct perf_probe_arg_field));
592 if (*fieldp == NULL)
593 return -ENOMEM;
460 if (*tmp == '.') { 594 if (*tmp == '.') {
461 str = tmp + 1; 595 str = tmp + 1;
462 (*fieldp)->ref = false; 596 (*fieldp)->ref = false;
463 } else if (tmp[1] == '>') { 597 } else if (tmp[1] == '>') {
464 str = tmp + 2; 598 str = tmp + 2;
465 (*fieldp)->ref = true; 599 (*fieldp)->ref = true;
466 } else 600 } else {
467 semantic_error("Argument parse error: %s", str); 601 semantic_error("Argument parse error: %s\n", str);
602 return -EINVAL;
603 }
468 604
469 tmp = strpbrk(str, "-."); 605 tmp = strpbrk(str, "-.");
470 if (tmp) { 606 if (tmp) {
471 (*fieldp)->name = xstrndup(str, tmp - str); 607 (*fieldp)->name = strndup(str, tmp - str);
608 if ((*fieldp)->name == NULL)
609 return -ENOMEM;
472 pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref); 610 pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref);
473 fieldp = &(*fieldp)->next; 611 fieldp = &(*fieldp)->next;
474 } 612 }
475 } while (tmp); 613 } while (tmp);
476 (*fieldp)->name = xstrdup(str); 614 (*fieldp)->name = strdup(str);
615 if ((*fieldp)->name == NULL)
616 return -ENOMEM;
477 pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref); 617 pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref);
618
619 /* If no name is specified, set the last field name */
620 if (!arg->name) {
621 arg->name = strdup((*fieldp)->name);
622 if (arg->name == NULL)
623 return -ENOMEM;
624 }
625 return 0;
478} 626}
479 627
480/* Parse perf-probe event command */ 628/* Parse perf-probe event command */
481void parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev) 629int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev)
482{ 630{
483 char **argv; 631 char **argv;
484 int argc, i; 632 int argc, i, ret = 0;
485 633
486 argv = argv_split(cmd, &argc); 634 argv = argv_split(cmd, &argc);
487 if (!argv) 635 if (!argv) {
488 die("argv_split failed."); 636 pr_debug("Failed to split arguments.\n");
489 if (argc > MAX_PROBE_ARGS + 1) 637 return -ENOMEM;
490 semantic_error("Too many arguments"); 638 }
491 639 if (argc - 1 > MAX_PROBE_ARGS) {
640 semantic_error("Too many probe arguments (%d).\n", argc - 1);
641 ret = -ERANGE;
642 goto out;
643 }
492 /* Parse probe point */ 644 /* Parse probe point */
493 parse_perf_probe_point(argv[0], pev); 645 ret = parse_perf_probe_point(argv[0], pev);
646 if (ret < 0)
647 goto out;
494 648
495 /* Copy arguments and ensure return probe has no C argument */ 649 /* Copy arguments and ensure return probe has no C argument */
496 pev->nargs = argc - 1; 650 pev->nargs = argc - 1;
497 pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs); 651 pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
498 for (i = 0; i < pev->nargs; i++) { 652 if (pev->args == NULL) {
499 parse_perf_probe_arg(argv[i + 1], &pev->args[i]); 653 ret = -ENOMEM;
500 if (is_c_varname(pev->args[i].name) && pev->point.retprobe) 654 goto out;
655 }
656 for (i = 0; i < pev->nargs && ret >= 0; i++) {
657 ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]);
658 if (ret >= 0 &&
659 is_c_varname(pev->args[i].var) && pev->point.retprobe) {
501 semantic_error("You can't specify local variable for" 660 semantic_error("You can't specify local variable for"
502 " kretprobe"); 661 " kretprobe.\n");
662 ret = -EINVAL;
663 }
503 } 664 }
504 665out:
505 argv_free(argv); 666 argv_free(argv);
667
668 return ret;
506} 669}
507 670
508/* Return true if this perf_probe_event requires debuginfo */ 671/* Return true if this perf_probe_event requires debuginfo */
@@ -514,14 +677,14 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
514 return true; 677 return true;
515 678
516 for (i = 0; i < pev->nargs; i++) 679 for (i = 0; i < pev->nargs; i++)
517 if (is_c_varname(pev->args[i].name)) 680 if (is_c_varname(pev->args[i].var))
518 return true; 681 return true;
519 682
520 return false; 683 return false;
521} 684}
522 685
523/* Parse kprobe_events event into struct probe_point */ 686/* Parse kprobe_events event into struct probe_point */
524void parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev) 687int parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev)
525{ 688{
526 struct kprobe_trace_point *tp = &tev->point; 689 struct kprobe_trace_point *tp = &tev->point;
527 char pr; 690 char pr;
@@ -531,17 +694,25 @@ void parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev)
531 694
532 pr_debug("Parsing kprobe_events: %s\n", cmd); 695 pr_debug("Parsing kprobe_events: %s\n", cmd);
533 argv = argv_split(cmd, &argc); 696 argv = argv_split(cmd, &argc);
534 if (!argv) 697 if (!argv) {
535 die("argv_split failed."); 698 pr_debug("Failed to split arguments.\n");
536 if (argc < 2) 699 return -ENOMEM;
537 semantic_error("Too less arguments."); 700 }
701 if (argc < 2) {
702 semantic_error("Too few probe arguments.\n");
703 ret = -ERANGE;
704 goto out;
705 }
538 706
539 /* Scan event and group name. */ 707 /* Scan event and group name. */
540 ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]", 708 ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]",
541 &pr, (float *)(void *)&tev->group, 709 &pr, (float *)(void *)&tev->group,
542 (float *)(void *)&tev->event); 710 (float *)(void *)&tev->event);
543 if (ret != 3) 711 if (ret != 3) {
544 semantic_error("Failed to parse event name: %s", argv[0]); 712 semantic_error("Failed to parse event name: %s\n", argv[0]);
713 ret = -EINVAL;
714 goto out;
715 }
545 pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr); 716 pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr);
546 717
547 tp->retprobe = (pr == 'r'); 718 tp->retprobe = (pr == 'r');
@@ -553,19 +724,29 @@ void parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev)
553 tp->offset = 0; 724 tp->offset = 0;
554 725
555 tev->nargs = argc - 2; 726 tev->nargs = argc - 2;
556 tev->args = xzalloc(sizeof(struct kprobe_trace_arg) * tev->nargs); 727 tev->args = zalloc(sizeof(struct kprobe_trace_arg) * tev->nargs);
728 if (tev->args == NULL) {
729 ret = -ENOMEM;
730 goto out;
731 }
557 for (i = 0; i < tev->nargs; i++) { 732 for (i = 0; i < tev->nargs; i++) {
558 p = strchr(argv[i + 2], '='); 733 p = strchr(argv[i + 2], '=');
559 if (p) /* We don't need which register is assigned. */ 734 if (p) /* We don't need which register is assigned. */
560 *p++ = '\0'; 735 *p++ = '\0';
561 else 736 else
562 p = argv[i + 2]; 737 p = argv[i + 2];
563 tev->args[i].name = xstrdup(argv[i + 2]); 738 tev->args[i].name = strdup(argv[i + 2]);
564 /* TODO: parse regs and offset */ 739 /* TODO: parse regs and offset */
565 tev->args[i].value = xstrdup(p); 740 tev->args[i].value = strdup(p);
741 if (tev->args[i].name == NULL || tev->args[i].value == NULL) {
742 ret = -ENOMEM;
743 goto out;
744 }
566 } 745 }
567 746 ret = 0;
747out:
568 argv_free(argv); 748 argv_free(argv);
749 return ret;
569} 750}
570 751
571/* Compose only probe arg */ 752/* Compose only probe arg */
@@ -575,7 +756,10 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
575 int ret; 756 int ret;
576 char *tmp = buf; 757 char *tmp = buf;
577 758
578 ret = e_snprintf(tmp, len, "%s", pa->name); 759 if (pa->name && pa->var)
760 ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var);
761 else
762 ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var);
579 if (ret <= 0) 763 if (ret <= 0)
580 goto error; 764 goto error;
581 tmp += ret; 765 tmp += ret;
@@ -590,9 +774,20 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
590 len -= ret; 774 len -= ret;
591 field = field->next; 775 field = field->next;
592 } 776 }
777
778 if (pa->type) {
779 ret = e_snprintf(tmp, len, ":%s", pa->type);
780 if (ret <= 0)
781 goto error;
782 tmp += ret;
783 len -= ret;
784 }
785
593 return tmp - buf; 786 return tmp - buf;
594error: 787error:
595 die("Failed to synthesize perf probe argument: %s", strerror(-ret)); 788 pr_debug("Failed to synthesize perf probe argument: %s",
789 strerror(-ret));
790 return ret;
596} 791}
597 792
598/* Compose only probe point (not argument) */ 793/* Compose only probe point (not argument) */
@@ -602,7 +797,11 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
602 char offs[32] = "", line[32] = "", file[32] = ""; 797 char offs[32] = "", line[32] = "", file[32] = "";
603 int ret, len; 798 int ret, len;
604 799
605 buf = xzalloc(MAX_CMDLEN); 800 buf = zalloc(MAX_CMDLEN);
801 if (buf == NULL) {
802 ret = -ENOMEM;
803 goto error;
804 }
606 if (pp->offset) { 805 if (pp->offset) {
607 ret = e_snprintf(offs, 32, "+%lu", pp->offset); 806 ret = e_snprintf(offs, 32, "+%lu", pp->offset);
608 if (ret <= 0) 807 if (ret <= 0)
@@ -614,12 +813,12 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
614 goto error; 813 goto error;
615 } 814 }
616 if (pp->file) { 815 if (pp->file) {
617 len = strlen(pp->file) - 32; 816 len = strlen(pp->file) - 31;
618 if (len < 0) 817 if (len < 0)
619 len = 0; 818 len = 0;
620 tmp = strchr(pp->file + len, '/'); 819 tmp = strchr(pp->file + len, '/');
621 if (!tmp) 820 if (!tmp)
622 tmp = pp->file + len - 1; 821 tmp = pp->file + len;
623 ret = e_snprintf(file, 32, "@%s", tmp + 1); 822 ret = e_snprintf(file, 32, "@%s", tmp + 1);
624 if (ret <= 0) 823 if (ret <= 0)
625 goto error; 824 goto error;
@@ -636,7 +835,11 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
636 835
637 return buf; 836 return buf;
638error: 837error:
639 die("Failed to synthesize perf probe point: %s", strerror(-ret)); 838 pr_debug("Failed to synthesize perf probe point: %s",
839 strerror(-ret));
840 if (buf)
841 free(buf);
842 return NULL;
640} 843}
641 844
642#if 0 845#if 0
@@ -727,6 +930,13 @@ static int synthesize_kprobe_trace_arg(struct kprobe_trace_arg *arg,
727 buf += ret; 930 buf += ret;
728 buflen -= ret; 931 buflen -= ret;
729 } 932 }
933 /* Print argument type */
934 if (arg->type) {
935 ret = e_snprintf(buf, buflen, ":%s", arg->type);
936 if (ret <= 0)
937 return ret;
938 buf += ret;
939 }
730 940
731 return buf - tmp; 941 return buf - tmp;
732} 942}
@@ -737,7 +947,10 @@ char *synthesize_kprobe_trace_command(struct kprobe_trace_event *tev)
737 char *buf; 947 char *buf;
738 int i, len, ret; 948 int i, len, ret;
739 949
740 buf = xzalloc(MAX_CMDLEN); 950 buf = zalloc(MAX_CMDLEN);
951 if (buf == NULL)
952 return NULL;
953
741 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu", 954 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu",
742 tp->retprobe ? 'r' : 'p', 955 tp->retprobe ? 'r' : 'p',
743 tev->group, tev->event, 956 tev->group, tev->event,
@@ -759,29 +972,44 @@ error:
759 return NULL; 972 return NULL;
760} 973}
761 974
762void convert_to_perf_probe_event(struct kprobe_trace_event *tev, 975int convert_to_perf_probe_event(struct kprobe_trace_event *tev,
763 struct perf_probe_event *pev) 976 struct perf_probe_event *pev)
764{ 977{
765 char buf[64]; 978 char buf[64] = "";
766 int i; 979 int i, ret;
767 980
768 /* Convert event/group name */ 981 /* Convert event/group name */
769 pev->event = xstrdup(tev->event); 982 pev->event = strdup(tev->event);
770 pev->group = xstrdup(tev->group); 983 pev->group = strdup(tev->group);
984 if (pev->event == NULL || pev->group == NULL)
985 return -ENOMEM;
771 986
772 /* Convert trace_point to probe_point */ 987 /* Convert trace_point to probe_point */
773 convert_to_perf_probe_point(&tev->point, &pev->point); 988 ret = convert_to_perf_probe_point(&tev->point, &pev->point);
989 if (ret < 0)
990 return ret;
774 991
775 /* Convert trace_arg to probe_arg */ 992 /* Convert trace_arg to probe_arg */
776 pev->nargs = tev->nargs; 993 pev->nargs = tev->nargs;
777 pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs); 994 pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
778 for (i = 0; i < tev->nargs; i++) 995 if (pev->args == NULL)
996 return -ENOMEM;
997 for (i = 0; i < tev->nargs && ret >= 0; i++) {
779 if (tev->args[i].name) 998 if (tev->args[i].name)
780 pev->args[i].name = xstrdup(tev->args[i].name); 999 pev->args[i].name = strdup(tev->args[i].name);
781 else { 1000 else {
782 synthesize_kprobe_trace_arg(&tev->args[i], buf, 64); 1001 ret = synthesize_kprobe_trace_arg(&tev->args[i],
783 pev->args[i].name = xstrdup(buf); 1002 buf, 64);
1003 pev->args[i].name = strdup(buf);
784 } 1004 }
1005 if (pev->args[i].name == NULL && ret >= 0)
1006 ret = -ENOMEM;
1007 }
1008
1009 if (ret < 0)
1010 clear_perf_probe_event(pev);
1011
1012 return ret;
785} 1013}
786 1014
787void clear_perf_probe_event(struct perf_probe_event *pev) 1015void clear_perf_probe_event(struct perf_probe_event *pev)
@@ -803,6 +1031,10 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
803 for (i = 0; i < pev->nargs; i++) { 1031 for (i = 0; i < pev->nargs; i++) {
804 if (pev->args[i].name) 1032 if (pev->args[i].name)
805 free(pev->args[i].name); 1033 free(pev->args[i].name);
1034 if (pev->args[i].var)
1035 free(pev->args[i].var);
1036 if (pev->args[i].type)
1037 free(pev->args[i].type);
806 field = pev->args[i].field; 1038 field = pev->args[i].field;
807 while (field) { 1039 while (field) {
808 next = field->next; 1040 next = field->next;
@@ -833,6 +1065,8 @@ void clear_kprobe_trace_event(struct kprobe_trace_event *tev)
833 free(tev->args[i].name); 1065 free(tev->args[i].name);
834 if (tev->args[i].value) 1066 if (tev->args[i].value)
835 free(tev->args[i].value); 1067 free(tev->args[i].value);
1068 if (tev->args[i].type)
1069 free(tev->args[i].type);
836 ref = tev->args[i].ref; 1070 ref = tev->args[i].ref;
837 while (ref) { 1071 while (ref) {
838 next = ref->next; 1072 next = ref->next;
@@ -848,24 +1082,31 @@ void clear_kprobe_trace_event(struct kprobe_trace_event *tev)
848static int open_kprobe_events(bool readwrite) 1082static int open_kprobe_events(bool readwrite)
849{ 1083{
850 char buf[PATH_MAX]; 1084 char buf[PATH_MAX];
1085 const char *__debugfs;
851 int ret; 1086 int ret;
852 1087
853 ret = e_snprintf(buf, PATH_MAX, "%s/../kprobe_events", debugfs_path); 1088 __debugfs = debugfs_find_mountpoint();
854 if (ret < 0) 1089 if (__debugfs == NULL) {
855 die("Failed to make kprobe_events path."); 1090 pr_warning("Debugfs is not mounted.\n");
1091 return -ENOENT;
1092 }
856 1093
857 if (readwrite && !probe_event_dry_run) 1094 ret = e_snprintf(buf, PATH_MAX, "%stracing/kprobe_events", __debugfs);
858 ret = open(buf, O_RDWR, O_APPEND); 1095 if (ret >= 0) {
859 else 1096 pr_debug("Opening %s write=%d\n", buf, readwrite);
860 ret = open(buf, O_RDONLY, 0); 1097 if (readwrite && !probe_event_dry_run)
1098 ret = open(buf, O_RDWR, O_APPEND);
1099 else
1100 ret = open(buf, O_RDONLY, 0);
1101 }
861 1102
862 if (ret < 0) { 1103 if (ret < 0) {
863 if (errno == ENOENT) 1104 if (errno == ENOENT)
864 die("kprobe_events file does not exist -" 1105 pr_warning("kprobe_events file does not exist - please"
865 " please rebuild with CONFIG_KPROBE_EVENT."); 1106 " rebuild kernel with CONFIG_KPROBE_EVENT.\n");
866 else 1107 else
867 die("Could not open kprobe_events file: %s", 1108 pr_warning("Failed to open kprobe_events file: %s\n",
868 strerror(errno)); 1109 strerror(errno));
869 } 1110 }
870 return ret; 1111 return ret;
871} 1112}
@@ -891,8 +1132,11 @@ static struct strlist *get_kprobe_trace_command_rawlist(int fd)
891 if (p[idx] == '\n') 1132 if (p[idx] == '\n')
892 p[idx] = '\0'; 1133 p[idx] = '\0';
893 ret = strlist__add(sl, buf); 1134 ret = strlist__add(sl, buf);
894 if (ret < 0) 1135 if (ret < 0) {
895 die("strlist__add failed: %s", strerror(-ret)); 1136 pr_debug("strlist__add failed: %s\n", strerror(-ret));
1137 strlist__delete(sl);
1138 return NULL;
1139 }
896 } 1140 }
897 fclose(fp); 1141 fclose(fp);
898 1142
@@ -900,7 +1144,7 @@ static struct strlist *get_kprobe_trace_command_rawlist(int fd)
900} 1144}
901 1145
902/* Show an event */ 1146/* Show an event */
903static void show_perf_probe_event(struct perf_probe_event *pev) 1147static int show_perf_probe_event(struct perf_probe_event *pev)
904{ 1148{
905 int i, ret; 1149 int i, ret;
906 char buf[128]; 1150 char buf[128];
@@ -908,52 +1152,71 @@ static void show_perf_probe_event(struct perf_probe_event *pev)
908 1152
909 /* Synthesize only event probe point */ 1153 /* Synthesize only event probe point */
910 place = synthesize_perf_probe_point(&pev->point); 1154 place = synthesize_perf_probe_point(&pev->point);
1155 if (!place)
1156 return -EINVAL;
911 1157
912 ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event); 1158 ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event);
913 if (ret < 0) 1159 if (ret < 0)
914 die("Failed to copy event: %s", strerror(-ret)); 1160 return ret;
1161
915 printf(" %-20s (on %s", buf, place); 1162 printf(" %-20s (on %s", buf, place);
916 1163
917 if (pev->nargs > 0) { 1164 if (pev->nargs > 0) {
918 printf(" with"); 1165 printf(" with");
919 for (i = 0; i < pev->nargs; i++) { 1166 for (i = 0; i < pev->nargs; i++) {
920 synthesize_perf_probe_arg(&pev->args[i], buf, 128); 1167 ret = synthesize_perf_probe_arg(&pev->args[i],
1168 buf, 128);
1169 if (ret < 0)
1170 break;
921 printf(" %s", buf); 1171 printf(" %s", buf);
922 } 1172 }
923 } 1173 }
924 printf(")\n"); 1174 printf(")\n");
925 free(place); 1175 free(place);
1176 return ret;
926} 1177}
927 1178
928/* List up current perf-probe events */ 1179/* List up current perf-probe events */
929void show_perf_probe_events(void) 1180int show_perf_probe_events(void)
930{ 1181{
931 int fd; 1182 int fd, ret;
932 struct kprobe_trace_event tev; 1183 struct kprobe_trace_event tev;
933 struct perf_probe_event pev; 1184 struct perf_probe_event pev;
934 struct strlist *rawlist; 1185 struct strlist *rawlist;
935 struct str_node *ent; 1186 struct str_node *ent;
936 1187
937 setup_pager(); 1188 setup_pager();
938 init_vmlinux(); 1189 ret = init_vmlinux();
1190 if (ret < 0)
1191 return ret;
939 1192
940 memset(&tev, 0, sizeof(tev)); 1193 memset(&tev, 0, sizeof(tev));
941 memset(&pev, 0, sizeof(pev)); 1194 memset(&pev, 0, sizeof(pev));
942 1195
943 fd = open_kprobe_events(false); 1196 fd = open_kprobe_events(false);
1197 if (fd < 0)
1198 return fd;
1199
944 rawlist = get_kprobe_trace_command_rawlist(fd); 1200 rawlist = get_kprobe_trace_command_rawlist(fd);
945 close(fd); 1201 close(fd);
1202 if (!rawlist)
1203 return -ENOENT;
946 1204
947 strlist__for_each(ent, rawlist) { 1205 strlist__for_each(ent, rawlist) {
948 parse_kprobe_trace_command(ent->s, &tev); 1206 ret = parse_kprobe_trace_command(ent->s, &tev);
949 convert_to_perf_probe_event(&tev, &pev); 1207 if (ret >= 0) {
950 /* Show an event */ 1208 ret = convert_to_perf_probe_event(&tev, &pev);
951 show_perf_probe_event(&pev); 1209 if (ret >= 0)
1210 ret = show_perf_probe_event(&pev);
1211 }
952 clear_perf_probe_event(&pev); 1212 clear_perf_probe_event(&pev);
953 clear_kprobe_trace_event(&tev); 1213 clear_kprobe_trace_event(&tev);
1214 if (ret < 0)
1215 break;
954 } 1216 }
955
956 strlist__delete(rawlist); 1217 strlist__delete(rawlist);
1218
1219 return ret;
957} 1220}
958 1221
959/* Get current perf-probe event names */ 1222/* Get current perf-probe event names */
@@ -963,86 +1226,116 @@ static struct strlist *get_kprobe_trace_event_names(int fd, bool include_group)
963 struct strlist *sl, *rawlist; 1226 struct strlist *sl, *rawlist;
964 struct str_node *ent; 1227 struct str_node *ent;
965 struct kprobe_trace_event tev; 1228 struct kprobe_trace_event tev;
1229 int ret = 0;
966 1230
967 memset(&tev, 0, sizeof(tev)); 1231 memset(&tev, 0, sizeof(tev));
968 1232
969 rawlist = get_kprobe_trace_command_rawlist(fd); 1233 rawlist = get_kprobe_trace_command_rawlist(fd);
970 sl = strlist__new(true, NULL); 1234 sl = strlist__new(true, NULL);
971 strlist__for_each(ent, rawlist) { 1235 strlist__for_each(ent, rawlist) {
972 parse_kprobe_trace_command(ent->s, &tev); 1236 ret = parse_kprobe_trace_command(ent->s, &tev);
1237 if (ret < 0)
1238 break;
973 if (include_group) { 1239 if (include_group) {
974 if (e_snprintf(buf, 128, "%s:%s", tev.group, 1240 ret = e_snprintf(buf, 128, "%s:%s", tev.group,
975 tev.event) < 0) 1241 tev.event);
976 die("Failed to copy group:event name."); 1242 if (ret >= 0)
977 strlist__add(sl, buf); 1243 ret = strlist__add(sl, buf);
978 } else 1244 } else
979 strlist__add(sl, tev.event); 1245 ret = strlist__add(sl, tev.event);
980 clear_kprobe_trace_event(&tev); 1246 clear_kprobe_trace_event(&tev);
1247 if (ret < 0)
1248 break;
981 } 1249 }
982
983 strlist__delete(rawlist); 1250 strlist__delete(rawlist);
984 1251
1252 if (ret < 0) {
1253 strlist__delete(sl);
1254 return NULL;
1255 }
985 return sl; 1256 return sl;
986} 1257}
987 1258
988static void write_kprobe_trace_event(int fd, struct kprobe_trace_event *tev) 1259static int write_kprobe_trace_event(int fd, struct kprobe_trace_event *tev)
989{ 1260{
990 int ret; 1261 int ret;
991 char *buf = synthesize_kprobe_trace_command(tev); 1262 char *buf = synthesize_kprobe_trace_command(tev);
992 1263
1264 if (!buf) {
1265 pr_debug("Failed to synthesize kprobe trace event.\n");
1266 return -EINVAL;
1267 }
1268
993 pr_debug("Writing event: %s\n", buf); 1269 pr_debug("Writing event: %s\n", buf);
994 if (!probe_event_dry_run) { 1270 if (!probe_event_dry_run) {
995 ret = write(fd, buf, strlen(buf)); 1271 ret = write(fd, buf, strlen(buf));
996 if (ret <= 0) 1272 if (ret <= 0)
997 die("Failed to write event: %s", strerror(errno)); 1273 pr_warning("Failed to write event: %s\n",
1274 strerror(errno));
998 } 1275 }
999 free(buf); 1276 free(buf);
1277 return ret;
1000} 1278}
1001 1279
1002static void get_new_event_name(char *buf, size_t len, const char *base, 1280static int get_new_event_name(char *buf, size_t len, const char *base,
1003 struct strlist *namelist, bool allow_suffix) 1281 struct strlist *namelist, bool allow_suffix)
1004{ 1282{
1005 int i, ret; 1283 int i, ret;
1006 1284
1007 /* Try no suffix */ 1285 /* Try no suffix */
1008 ret = e_snprintf(buf, len, "%s", base); 1286 ret = e_snprintf(buf, len, "%s", base);
1009 if (ret < 0) 1287 if (ret < 0) {
1010 die("snprintf() failed: %s", strerror(-ret)); 1288 pr_debug("snprintf() failed: %s\n", strerror(-ret));
1289 return ret;
1290 }
1011 if (!strlist__has_entry(namelist, buf)) 1291 if (!strlist__has_entry(namelist, buf))
1012 return; 1292 return 0;
1013 1293
1014 if (!allow_suffix) { 1294 if (!allow_suffix) {
1015 pr_warning("Error: event \"%s\" already exists. " 1295 pr_warning("Error: event \"%s\" already exists. "
1016 "(Use -f to force duplicates.)\n", base); 1296 "(Use -f to force duplicates.)\n", base);
1017 die("Can't add new event."); 1297 return -EEXIST;
1018 } 1298 }
1019 1299
1020 /* Try to add suffix */ 1300 /* Try to add suffix */
1021 for (i = 1; i < MAX_EVENT_INDEX; i++) { 1301 for (i = 1; i < MAX_EVENT_INDEX; i++) {
1022 ret = e_snprintf(buf, len, "%s_%d", base, i); 1302 ret = e_snprintf(buf, len, "%s_%d", base, i);
1023 if (ret < 0) 1303 if (ret < 0) {
1024 die("snprintf() failed: %s", strerror(-ret)); 1304 pr_debug("snprintf() failed: %s\n", strerror(-ret));
1305 return ret;
1306 }
1025 if (!strlist__has_entry(namelist, buf)) 1307 if (!strlist__has_entry(namelist, buf))
1026 break; 1308 break;
1027 } 1309 }
1028 if (i == MAX_EVENT_INDEX) 1310 if (i == MAX_EVENT_INDEX) {
1029 die("Too many events are on the same function."); 1311 pr_warning("Too many events are on the same function.\n");
1312 ret = -ERANGE;
1313 }
1314
1315 return ret;
1030} 1316}
1031 1317
1032static void __add_kprobe_trace_events(struct perf_probe_event *pev, 1318static int __add_kprobe_trace_events(struct perf_probe_event *pev,
1033 struct kprobe_trace_event *tevs, 1319 struct kprobe_trace_event *tevs,
1034 int ntevs, bool allow_suffix) 1320 int ntevs, bool allow_suffix)
1035{ 1321{
1036 int i, fd; 1322 int i, fd, ret;
1037 struct kprobe_trace_event *tev = NULL; 1323 struct kprobe_trace_event *tev = NULL;
1038 char buf[64]; 1324 char buf[64];
1039 const char *event, *group; 1325 const char *event, *group;
1040 struct strlist *namelist; 1326 struct strlist *namelist;
1041 1327
1042 fd = open_kprobe_events(true); 1328 fd = open_kprobe_events(true);
1329 if (fd < 0)
1330 return fd;
1043 /* Get current event names */ 1331 /* Get current event names */
1044 namelist = get_kprobe_trace_event_names(fd, false); 1332 namelist = get_kprobe_trace_event_names(fd, false);
1333 if (!namelist) {
1334 pr_debug("Failed to get current event list.\n");
1335 return -EIO;
1336 }
1045 1337
1338 ret = 0;
1046 printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":"); 1339 printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":");
1047 for (i = 0; i < ntevs; i++) { 1340 for (i = 0; i < ntevs; i++) {
1048 tev = &tevs[i]; 1341 tev = &tevs[i];
@@ -1059,12 +1352,21 @@ static void __add_kprobe_trace_events(struct perf_probe_event *pev,
1059 group = PERFPROBE_GROUP; 1352 group = PERFPROBE_GROUP;
1060 1353
1061 /* Get an unused new event name */ 1354 /* Get an unused new event name */
1062 get_new_event_name(buf, 64, event, namelist, allow_suffix); 1355 ret = get_new_event_name(buf, 64, event,
1356 namelist, allow_suffix);
1357 if (ret < 0)
1358 break;
1063 event = buf; 1359 event = buf;
1064 1360
1065 tev->event = xstrdup(event); 1361 tev->event = strdup(event);
1066 tev->group = xstrdup(group); 1362 tev->group = strdup(group);
1067 write_kprobe_trace_event(fd, tev); 1363 if (tev->event == NULL || tev->group == NULL) {
1364 ret = -ENOMEM;
1365 break;
1366 }
1367 ret = write_kprobe_trace_event(fd, tev);
1368 if (ret < 0)
1369 break;
1068 /* Add added event name to namelist */ 1370 /* Add added event name to namelist */
1069 strlist__add(namelist, event); 1371 strlist__add(namelist, event);
1070 1372
@@ -1086,49 +1388,90 @@ static void __add_kprobe_trace_events(struct perf_probe_event *pev,
1086 */ 1388 */
1087 allow_suffix = true; 1389 allow_suffix = true;
1088 } 1390 }
1089 /* Show how to use the event. */ 1391
1090 printf("\nYou can now use it on all perf tools, such as:\n\n"); 1392 if (ret >= 0) {
1091 printf("\tperf record -e %s:%s -a sleep 1\n\n", tev->group, tev->event); 1393 /* Show how to use the event. */
1394 printf("\nYou can now use it on all perf tools, such as:\n\n");
1395 printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
1396 tev->event);
1397 }
1092 1398
1093 strlist__delete(namelist); 1399 strlist__delete(namelist);
1094 close(fd); 1400 close(fd);
1401 return ret;
1095} 1402}
1096 1403
1097static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, 1404static int convert_to_kprobe_trace_events(struct perf_probe_event *pev,
1098 struct kprobe_trace_event **tevs) 1405 struct kprobe_trace_event **tevs)
1099{ 1406{
1100 struct symbol *sym; 1407 struct symbol *sym;
1101 int ntevs = 0, i; 1408 int ret = 0, i;
1102 struct kprobe_trace_event *tev; 1409 struct kprobe_trace_event *tev;
1103 1410
1104 /* Convert perf_probe_event with debuginfo */ 1411 /* Convert perf_probe_event with debuginfo */
1105 ntevs = try_to_find_kprobe_trace_events(pev, tevs); 1412 ret = try_to_find_kprobe_trace_events(pev, tevs);
1106 if (ntevs > 0) 1413 if (ret != 0)
1107 return ntevs; 1414 return ret;
1108 1415
1109 /* Allocate trace event buffer */ 1416 /* Allocate trace event buffer */
1110 ntevs = 1; 1417 tev = *tevs = zalloc(sizeof(struct kprobe_trace_event));
1111 tev = *tevs = xzalloc(sizeof(struct kprobe_trace_event)); 1418 if (tev == NULL)
1419 return -ENOMEM;
1112 1420
1113 /* Copy parameters */ 1421 /* Copy parameters */
1114 tev->point.symbol = xstrdup(pev->point.function); 1422 tev->point.symbol = strdup(pev->point.function);
1423 if (tev->point.symbol == NULL) {
1424 ret = -ENOMEM;
1425 goto error;
1426 }
1115 tev->point.offset = pev->point.offset; 1427 tev->point.offset = pev->point.offset;
1116 tev->nargs = pev->nargs; 1428 tev->nargs = pev->nargs;
1117 if (tev->nargs) { 1429 if (tev->nargs) {
1118 tev->args = xzalloc(sizeof(struct kprobe_trace_arg) 1430 tev->args = zalloc(sizeof(struct kprobe_trace_arg)
1119 * tev->nargs); 1431 * tev->nargs);
1120 for (i = 0; i < tev->nargs; i++) 1432 if (tev->args == NULL) {
1121 tev->args[i].value = xstrdup(pev->args[i].name); 1433 ret = -ENOMEM;
1434 goto error;
1435 }
1436 for (i = 0; i < tev->nargs; i++) {
1437 if (pev->args[i].name) {
1438 tev->args[i].name = strdup(pev->args[i].name);
1439 if (tev->args[i].name == NULL) {
1440 ret = -ENOMEM;
1441 goto error;
1442 }
1443 }
1444 tev->args[i].value = strdup(pev->args[i].var);
1445 if (tev->args[i].value == NULL) {
1446 ret = -ENOMEM;
1447 goto error;
1448 }
1449 if (pev->args[i].type) {
1450 tev->args[i].type = strdup(pev->args[i].type);
1451 if (tev->args[i].type == NULL) {
1452 ret = -ENOMEM;
1453 goto error;
1454 }
1455 }
1456 }
1122 } 1457 }
1123 1458
1124 /* Currently just checking function name from symbol map */ 1459 /* Currently just checking function name from symbol map */
1125 sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], 1460 sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION],
1126 tev->point.symbol, NULL); 1461 tev->point.symbol, NULL);
1127 if (!sym) 1462 if (!sym) {
1128 die("Kernel symbol \'%s\' not found - probe not added.", 1463 pr_warning("Kernel symbol \'%s\' not found.\n",
1129 tev->point.symbol); 1464 tev->point.symbol);
1465 ret = -ENOENT;
1466 goto error;
1467 }
1130 1468
1131 return ntevs; 1469 return 1;
1470error:
1471 clear_kprobe_trace_event(tev);
1472 free(tev);
1473 *tevs = NULL;
1474 return ret;
1132} 1475}
1133 1476
1134struct __event_package { 1477struct __event_package {
@@ -1137,96 +1480,137 @@ struct __event_package {
1137 int ntevs; 1480 int ntevs;
1138}; 1481};
1139 1482
1140void add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 1483int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1141 bool force_add) 1484 bool force_add)
1142{ 1485{
1143 int i; 1486 int i, j, ret;
1144 struct __event_package *pkgs; 1487 struct __event_package *pkgs;
1145 1488
1146 pkgs = xzalloc(sizeof(struct __event_package) * npevs); 1489 pkgs = zalloc(sizeof(struct __event_package) * npevs);
1490 if (pkgs == NULL)
1491 return -ENOMEM;
1147 1492
1148 /* Init vmlinux path */ 1493 /* Init vmlinux path */
1149 init_vmlinux(); 1494 ret = init_vmlinux();
1495 if (ret < 0)
1496 return ret;
1150 1497
1151 /* Loop 1: convert all events */ 1498 /* Loop 1: convert all events */
1152 for (i = 0; i < npevs; i++) { 1499 for (i = 0; i < npevs; i++) {
1153 pkgs[i].pev = &pevs[i]; 1500 pkgs[i].pev = &pevs[i];
1154 /* Convert with or without debuginfo */ 1501 /* Convert with or without debuginfo */
1155 pkgs[i].ntevs = convert_to_kprobe_trace_events(pkgs[i].pev, 1502 ret = convert_to_kprobe_trace_events(pkgs[i].pev,
1156 &pkgs[i].tevs); 1503 &pkgs[i].tevs);
1504 if (ret < 0)
1505 goto end;
1506 pkgs[i].ntevs = ret;
1157 } 1507 }
1158 1508
1159 /* Loop 2: add all events */ 1509 /* Loop 2: add all events */
1510 for (i = 0; i < npevs && ret >= 0; i++)
1511 ret = __add_kprobe_trace_events(pkgs[i].pev, pkgs[i].tevs,
1512 pkgs[i].ntevs, force_add);
1513end:
1514 /* Loop 3: cleanup trace events */
1160 for (i = 0; i < npevs; i++) 1515 for (i = 0; i < npevs; i++)
1161 __add_kprobe_trace_events(pkgs[i].pev, pkgs[i].tevs, 1516 for (j = 0; j < pkgs[i].ntevs; j++)
1162 pkgs[i].ntevs, force_add); 1517 clear_kprobe_trace_event(&pkgs[i].tevs[j]);
1163 /* TODO: cleanup all trace events? */ 1518
1519 return ret;
1164} 1520}
1165 1521
1166static void __del_trace_kprobe_event(int fd, struct str_node *ent) 1522static int __del_trace_kprobe_event(int fd, struct str_node *ent)
1167{ 1523{
1168 char *p; 1524 char *p;
1169 char buf[128]; 1525 char buf[128];
1170 int ret; 1526 int ret;
1171 1527
1172 /* Convert from perf-probe event to trace-kprobe event */ 1528 /* Convert from perf-probe event to trace-kprobe event */
1173 if (e_snprintf(buf, 128, "-:%s", ent->s) < 0) 1529 ret = e_snprintf(buf, 128, "-:%s", ent->s);
1174 die("Failed to copy event."); 1530 if (ret < 0)
1531 goto error;
1532
1175 p = strchr(buf + 2, ':'); 1533 p = strchr(buf + 2, ':');
1176 if (!p) 1534 if (!p) {
1177 die("Internal error: %s should have ':' but not.", ent->s); 1535 pr_debug("Internal error: %s should have ':' but not.\n",
1536 ent->s);
1537 ret = -ENOTSUP;
1538 goto error;
1539 }
1178 *p = '/'; 1540 *p = '/';
1179 1541
1180 pr_debug("Writing event: %s\n", buf); 1542 pr_debug("Writing event: %s\n", buf);
1181 ret = write(fd, buf, strlen(buf)); 1543 ret = write(fd, buf, strlen(buf));
1182 if (ret <= 0) 1544 if (ret < 0)
1183 die("Failed to write event: %s", strerror(errno)); 1545 goto error;
1546
1184 printf("Remove event: %s\n", ent->s); 1547 printf("Remove event: %s\n", ent->s);
1548 return 0;
1549error:
1550 pr_warning("Failed to delete event: %s\n", strerror(-ret));
1551 return ret;
1185} 1552}
1186 1553
1187static void del_trace_kprobe_event(int fd, const char *group, 1554static int del_trace_kprobe_event(int fd, const char *group,
1188 const char *event, struct strlist *namelist) 1555 const char *event, struct strlist *namelist)
1189{ 1556{
1190 char buf[128]; 1557 char buf[128];
1191 struct str_node *ent, *n; 1558 struct str_node *ent, *n;
1192 int found = 0; 1559 int found = 0, ret = 0;
1193 1560
1194 if (e_snprintf(buf, 128, "%s:%s", group, event) < 0) 1561 ret = e_snprintf(buf, 128, "%s:%s", group, event);
1195 die("Failed to copy event."); 1562 if (ret < 0) {
1563 pr_err("Failed to copy event.");
1564 return ret;
1565 }
1196 1566
1197 if (strpbrk(buf, "*?")) { /* Glob-exp */ 1567 if (strpbrk(buf, "*?")) { /* Glob-exp */
1198 strlist__for_each_safe(ent, n, namelist) 1568 strlist__for_each_safe(ent, n, namelist)
1199 if (strglobmatch(ent->s, buf)) { 1569 if (strglobmatch(ent->s, buf)) {
1200 found++; 1570 found++;
1201 __del_trace_kprobe_event(fd, ent); 1571 ret = __del_trace_kprobe_event(fd, ent);
1572 if (ret < 0)
1573 break;
1202 strlist__remove(namelist, ent); 1574 strlist__remove(namelist, ent);
1203 } 1575 }
1204 } else { 1576 } else {
1205 ent = strlist__find(namelist, buf); 1577 ent = strlist__find(namelist, buf);
1206 if (ent) { 1578 if (ent) {
1207 found++; 1579 found++;
1208 __del_trace_kprobe_event(fd, ent); 1580 ret = __del_trace_kprobe_event(fd, ent);
1209 strlist__remove(namelist, ent); 1581 if (ret >= 0)
1582 strlist__remove(namelist, ent);
1210 } 1583 }
1211 } 1584 }
1212 if (found == 0) 1585 if (found == 0 && ret >= 0)
1213 pr_info("Info: event \"%s\" does not exist, could not remove it.\n", buf); 1586 pr_info("Info: Event \"%s\" does not exist.\n", buf);
1587
1588 return ret;
1214} 1589}
1215 1590
1216void del_perf_probe_events(struct strlist *dellist) 1591int del_perf_probe_events(struct strlist *dellist)
1217{ 1592{
1218 int fd; 1593 int fd, ret = 0;
1219 const char *group, *event; 1594 const char *group, *event;
1220 char *p, *str; 1595 char *p, *str;
1221 struct str_node *ent; 1596 struct str_node *ent;
1222 struct strlist *namelist; 1597 struct strlist *namelist;
1223 1598
1224 fd = open_kprobe_events(true); 1599 fd = open_kprobe_events(true);
1600 if (fd < 0)
1601 return fd;
1602
1225 /* Get current event names */ 1603 /* Get current event names */
1226 namelist = get_kprobe_trace_event_names(fd, true); 1604 namelist = get_kprobe_trace_event_names(fd, true);
1605 if (namelist == NULL)
1606 return -EINVAL;
1227 1607
1228 strlist__for_each(ent, dellist) { 1608 strlist__for_each(ent, dellist) {
1229 str = xstrdup(ent->s); 1609 str = strdup(ent->s);
1610 if (str == NULL) {
1611 ret = -ENOMEM;
1612 break;
1613 }
1230 pr_debug("Parsing: %s\n", str); 1614 pr_debug("Parsing: %s\n", str);
1231 p = strchr(str, ':'); 1615 p = strchr(str, ':');
1232 if (p) { 1616 if (p) {
@@ -1238,10 +1622,14 @@ void del_perf_probe_events(struct strlist *dellist)
1238 event = str; 1622 event = str;
1239 } 1623 }
1240 pr_debug("Group: %s, Event: %s\n", group, event); 1624 pr_debug("Group: %s, Event: %s\n", group, event);
1241 del_trace_kprobe_event(fd, group, event, namelist); 1625 ret = del_trace_kprobe_event(fd, group, event, namelist);
1242 free(str); 1626 free(str);
1627 if (ret < 0)
1628 break;
1243 } 1629 }
1244 strlist__delete(namelist); 1630 strlist__delete(namelist);
1245 close(fd); 1631 close(fd);
1632
1633 return ret;
1246} 1634}
1247 1635
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 9d99fc24c4fc..e7ff0d02c0d4 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -23,6 +23,7 @@ struct kprobe_trace_arg_ref {
23struct kprobe_trace_arg { 23struct kprobe_trace_arg {
24 char *name; /* Argument name */ 24 char *name; /* Argument name */
25 char *value; /* Base value */ 25 char *value; /* Base value */
26 char *type; /* Type name */
26 struct kprobe_trace_arg_ref *ref; /* Referencing offset */ 27 struct kprobe_trace_arg_ref *ref; /* Referencing offset */
27}; 28};
28 29
@@ -55,6 +56,8 @@ struct perf_probe_arg_field {
55/* Perf probe probing argument */ 56/* Perf probe probing argument */
56struct perf_probe_arg { 57struct perf_probe_arg {
57 char *name; /* Argument name */ 58 char *name; /* Argument name */
59 char *var; /* Variable name */
60 char *type; /* Type name */
58 struct perf_probe_arg_field *field; /* Structure fields */ 61 struct perf_probe_arg_field *field; /* Structure fields */
59}; 62};
60 63
@@ -71,25 +74,25 @@ struct perf_probe_event {
71/* Line number container */ 74/* Line number container */
72struct line_node { 75struct line_node {
73 struct list_head list; 76 struct list_head list;
74 unsigned int line; 77 int line;
75}; 78};
76 79
77/* Line range */ 80/* Line range */
78struct line_range { 81struct line_range {
79 char *file; /* File name */ 82 char *file; /* File name */
80 char *function; /* Function name */ 83 char *function; /* Function name */
81 unsigned int start; /* Start line number */ 84 int start; /* Start line number */
82 unsigned int end; /* End line number */ 85 int end; /* End line number */
83 int offset; /* Start line offset */ 86 int offset; /* Start line offset */
84 char *path; /* Real path name */ 87 char *path; /* Real path name */
85 struct list_head line_list; /* Visible lines */ 88 struct list_head line_list; /* Visible lines */
86}; 89};
87 90
88/* Command string to events */ 91/* Command string to events */
89extern void parse_perf_probe_command(const char *cmd, 92extern int parse_perf_probe_command(const char *cmd,
90 struct perf_probe_event *pev); 93 struct perf_probe_event *pev);
91extern void parse_kprobe_trace_command(const char *cmd, 94extern int parse_kprobe_trace_command(const char *cmd,
92 struct kprobe_trace_event *tev); 95 struct kprobe_trace_event *tev);
93 96
94/* Events to command string */ 97/* Events to command string */
95extern char *synthesize_perf_probe_command(struct perf_probe_event *pev); 98extern char *synthesize_perf_probe_command(struct perf_probe_event *pev);
@@ -101,22 +104,22 @@ extern int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf,
101extern bool perf_probe_event_need_dwarf(struct perf_probe_event *pev); 104extern bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
102 105
103/* Convert from kprobe_trace_event to perf_probe_event */ 106/* Convert from kprobe_trace_event to perf_probe_event */
104extern void convert_to_perf_probe_event(struct kprobe_trace_event *tev, 107extern int convert_to_perf_probe_event(struct kprobe_trace_event *tev,
105 struct perf_probe_event *pev); 108 struct perf_probe_event *pev);
106 109
107/* Release event contents */ 110/* Release event contents */
108extern void clear_perf_probe_event(struct perf_probe_event *pev); 111extern void clear_perf_probe_event(struct perf_probe_event *pev);
109extern void clear_kprobe_trace_event(struct kprobe_trace_event *tev); 112extern void clear_kprobe_trace_event(struct kprobe_trace_event *tev);
110 113
111/* Command string to line-range */ 114/* Command string to line-range */
112extern void parse_line_range_desc(const char *cmd, struct line_range *lr); 115extern int parse_line_range_desc(const char *cmd, struct line_range *lr);
113 116
114 117
115extern void add_perf_probe_events(struct perf_probe_event *pevs, int ntevs, 118extern int add_perf_probe_events(struct perf_probe_event *pevs, int ntevs,
116 bool force_add); 119 bool force_add);
117extern void del_perf_probe_events(struct strlist *dellist); 120extern int del_perf_probe_events(struct strlist *dellist);
118extern void show_perf_probe_events(void); 121extern int show_perf_probe_events(void);
119extern void show_line_range(struct line_range *lr); 122extern int show_line_range(struct line_range *lr);
120 123
121 124
122/* Maximum index number of event-name postfix */ 125/* Maximum index number of event-name postfix */
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index a8513772df08..3e7977560be5 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -84,6 +84,9 @@ const char *x86_64_regs_table[X86_64_MAX_REGS] = {
84#define arch_regs_table x86_32_regs_table 84#define arch_regs_table x86_32_regs_table
85#endif 85#endif
86 86
87/* Kprobe tracer basic type is up to u64 */
88#define MAX_BASIC_TYPE_BITS 64
89
87/* Return architecture dependent register string (for kprobe-tracer) */ 90/* Return architecture dependent register string (for kprobe-tracer) */
88static const char *get_arch_regstr(unsigned int n) 91static const char *get_arch_regstr(unsigned int n)
89{ 92{
@@ -108,7 +111,7 @@ static int strtailcmp(const char *s1, const char *s2)
108/* Line number list operations */ 111/* Line number list operations */
109 112
110/* Add a line to line number list */ 113/* Add a line to line number list */
111static void line_list__add_line(struct list_head *head, unsigned int line) 114static int line_list__add_line(struct list_head *head, int line)
112{ 115{
113 struct line_node *ln; 116 struct line_node *ln;
114 struct list_head *p; 117 struct list_head *p;
@@ -119,20 +122,23 @@ static void line_list__add_line(struct list_head *head, unsigned int line)
119 p = &ln->list; 122 p = &ln->list;
120 goto found; 123 goto found;
121 } else if (ln->line == line) /* Already exist */ 124 } else if (ln->line == line) /* Already exist */
122 return ; 125 return 1;
123 } 126 }
124 /* List is empty, or the smallest entry */ 127 /* List is empty, or the smallest entry */
125 p = head; 128 p = head;
126found: 129found:
127 pr_debug("line list: add a line %u\n", line); 130 pr_debug("line list: add a line %u\n", line);
128 ln = xzalloc(sizeof(struct line_node)); 131 ln = zalloc(sizeof(struct line_node));
132 if (ln == NULL)
133 return -ENOMEM;
129 ln->line = line; 134 ln->line = line;
130 INIT_LIST_HEAD(&ln->list); 135 INIT_LIST_HEAD(&ln->list);
131 list_add(&ln->list, p); 136 list_add(&ln->list, p);
137 return 0;
132} 138}
133 139
134/* Check if the line in line number list */ 140/* Check if the line in line number list */
135static int line_list__has_line(struct list_head *head, unsigned int line) 141static int line_list__has_line(struct list_head *head, int line)
136{ 142{
137 struct line_node *ln; 143 struct line_node *ln;
138 144
@@ -193,19 +199,7 @@ static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
193{ 199{
194 const char *name; 200 const char *name;
195 name = dwarf_diename(dw_die); 201 name = dwarf_diename(dw_die);
196 DIE_IF(name == NULL); 202 return name ? strcmp(tname, name) : -1;
197 return strcmp(tname, name);
198}
199
200/* Get entry pc(or low pc, 1st entry of ranges) of the die */
201static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die)
202{
203 Dwarf_Addr epc;
204 int ret;
205
206 ret = dwarf_entrypc(dw_die, &epc);
207 DIE_IF(ret == -1);
208 return epc;
209} 203}
210 204
211/* Get type die, but skip qualifiers and typedef */ 205/* Get type die, but skip qualifiers and typedef */
@@ -230,6 +224,58 @@ static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
230 return die_mem; 224 return die_mem;
231} 225}
232 226
227static bool die_is_signed_type(Dwarf_Die *tp_die)
228{
229 Dwarf_Attribute attr;
230 Dwarf_Word ret;
231
232 if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL ||
233 dwarf_formudata(&attr, &ret) != 0)
234 return false;
235
236 return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
237 ret == DW_ATE_signed_fixed);
238}
239
240static int die_get_byte_size(Dwarf_Die *tp_die)
241{
242 Dwarf_Attribute attr;
243 Dwarf_Word ret;
244
245 if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL ||
246 dwarf_formudata(&attr, &ret) != 0)
247 return 0;
248
249 return (int)ret;
250}
251
252/* Get data_member_location offset */
253static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
254{
255 Dwarf_Attribute attr;
256 Dwarf_Op *expr;
257 size_t nexpr;
258 int ret;
259
260 if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
261 return -ENOENT;
262
263 if (dwarf_formudata(&attr, offs) != 0) {
264 /* DW_AT_data_member_location should be DW_OP_plus_uconst */
265 ret = dwarf_getlocation(&attr, &expr, &nexpr);
266 if (ret < 0 || nexpr == 0)
267 return -ENOENT;
268
269 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
270 pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
271 expr[0].atom, nexpr);
272 return -ENOTSUP;
273 }
274 *offs = (Dwarf_Word)expr[0].number;
275 }
276 return 0;
277}
278
233/* Return values for die_find callbacks */ 279/* Return values for die_find callbacks */
234enum { 280enum {
235 DIE_FIND_CB_FOUND = 0, /* End of Search */ 281 DIE_FIND_CB_FOUND = 0, /* End of Search */
@@ -362,7 +408,7 @@ static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
362 */ 408 */
363 409
364/* Show a location */ 410/* Show a location */
365static void convert_location(Dwarf_Op *op, struct probe_finder *pf) 411static int convert_location(Dwarf_Op *op, struct probe_finder *pf)
366{ 412{
367 unsigned int regn; 413 unsigned int regn;
368 Dwarf_Word offs = 0; 414 Dwarf_Word offs = 0;
@@ -370,11 +416,13 @@ static void convert_location(Dwarf_Op *op, struct probe_finder *pf)
370 const char *regs; 416 const char *regs;
371 struct kprobe_trace_arg *tvar = pf->tvar; 417 struct kprobe_trace_arg *tvar = pf->tvar;
372 418
373 /* TODO: support CFA */
374 /* If this is based on frame buffer, set the offset */ 419 /* If this is based on frame buffer, set the offset */
375 if (op->atom == DW_OP_fbreg) { 420 if (op->atom == DW_OP_fbreg) {
376 if (pf->fb_ops == NULL) 421 if (pf->fb_ops == NULL) {
377 die("The attribute of frame base is not supported.\n"); 422 pr_warning("The attribute of frame base is not "
423 "supported.\n");
424 return -ENOTSUP;
425 }
378 ref = true; 426 ref = true;
379 offs = op->number; 427 offs = op->number;
380 op = &pf->fb_ops[0]; 428 op = &pf->fb_ops[0];
@@ -392,84 +440,155 @@ static void convert_location(Dwarf_Op *op, struct probe_finder *pf)
392 ref = true; 440 ref = true;
393 } else if (op->atom == DW_OP_regx) { 441 } else if (op->atom == DW_OP_regx) {
394 regn = op->number; 442 regn = op->number;
395 } else 443 } else {
396 die("DW_OP %d is not supported.", op->atom); 444 pr_warning("DW_OP %x is not supported.\n", op->atom);
445 return -ENOTSUP;
446 }
397 447
398 regs = get_arch_regstr(regn); 448 regs = get_arch_regstr(regn);
399 if (!regs) 449 if (!regs) {
400 die("%u exceeds max register number.", regn); 450 pr_warning("%u exceeds max register number.\n", regn);
451 return -ERANGE;
452 }
453
454 tvar->value = strdup(regs);
455 if (tvar->value == NULL)
456 return -ENOMEM;
401 457
402 tvar->value = xstrdup(regs);
403 if (ref) { 458 if (ref) {
404 tvar->ref = xzalloc(sizeof(struct kprobe_trace_arg_ref)); 459 tvar->ref = zalloc(sizeof(struct kprobe_trace_arg_ref));
460 if (tvar->ref == NULL)
461 return -ENOMEM;
405 tvar->ref->offset = (long)offs; 462 tvar->ref->offset = (long)offs;
406 } 463 }
464 return 0;
465}
466
467static int convert_variable_type(Dwarf_Die *vr_die,
468 struct kprobe_trace_arg *targ)
469{
470 Dwarf_Die type;
471 char buf[16];
472 int ret;
473
474 if (die_get_real_type(vr_die, &type) == NULL) {
475 pr_warning("Failed to get a type information of %s.\n",
476 dwarf_diename(vr_die));
477 return -ENOENT;
478 }
479
480 ret = die_get_byte_size(&type) * 8;
481 if (ret) {
482 /* Check the bitwidth */
483 if (ret > MAX_BASIC_TYPE_BITS) {
484 pr_info("%s exceeds max-bitwidth."
485 " Cut down to %d bits.\n",
486 dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
487 ret = MAX_BASIC_TYPE_BITS;
488 }
489
490 ret = snprintf(buf, 16, "%c%d",
491 die_is_signed_type(&type) ? 's' : 'u', ret);
492 if (ret < 0 || ret >= 16) {
493 if (ret >= 16)
494 ret = -E2BIG;
495 pr_warning("Failed to convert variable type: %s\n",
496 strerror(-ret));
497 return ret;
498 }
499 targ->type = strdup(buf);
500 if (targ->type == NULL)
501 return -ENOMEM;
502 }
503 return 0;
407} 504}
408 505
409static void convert_variable_fields(Dwarf_Die *vr_die, const char *varname, 506static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
410 struct perf_probe_arg_field *field, 507 struct perf_probe_arg_field *field,
411 struct kprobe_trace_arg_ref **ref_ptr) 508 struct kprobe_trace_arg_ref **ref_ptr,
509 Dwarf_Die *die_mem)
412{ 510{
413 struct kprobe_trace_arg_ref *ref = *ref_ptr; 511 struct kprobe_trace_arg_ref *ref = *ref_ptr;
414 Dwarf_Attribute attr;
415 Dwarf_Die member;
416 Dwarf_Die type; 512 Dwarf_Die type;
417 Dwarf_Word offs; 513 Dwarf_Word offs;
514 int ret;
418 515
419 pr_debug("converting %s in %s\n", field->name, varname); 516 pr_debug("converting %s in %s\n", field->name, varname);
420 if (die_get_real_type(vr_die, &type) == NULL) 517 if (die_get_real_type(vr_die, &type) == NULL) {
421 die("Failed to get a type information of %s.", varname); 518 pr_warning("Failed to get the type of %s.\n", varname);
519 return -ENOENT;
520 }
422 521
423 /* Check the pointer and dereference */ 522 /* Check the pointer and dereference */
424 if (dwarf_tag(&type) == DW_TAG_pointer_type) { 523 if (dwarf_tag(&type) == DW_TAG_pointer_type) {
425 if (!field->ref) 524 if (!field->ref) {
426 die("Semantic error: %s must be referred by '->'", 525 pr_err("Semantic error: %s must be referred by '->'\n",
427 field->name); 526 field->name);
527 return -EINVAL;
528 }
428 /* Get the type pointed by this pointer */ 529 /* Get the type pointed by this pointer */
429 if (die_get_real_type(&type, &type) == NULL) 530 if (die_get_real_type(&type, &type) == NULL) {
430 die("Failed to get a type information of %s.", varname); 531 pr_warning("Failed to get the type of %s.\n", varname);
431 532 return -ENOENT;
533 }
432 /* Verify it is a data structure */ 534 /* Verify it is a data structure */
433 if (dwarf_tag(&type) != DW_TAG_structure_type) 535 if (dwarf_tag(&type) != DW_TAG_structure_type) {
434 die("%s is not a data structure.", varname); 536 pr_warning("%s is not a data structure.\n", varname);
537 return -EINVAL;
538 }
435 539
436 ref = xzalloc(sizeof(struct kprobe_trace_arg_ref)); 540 ref = zalloc(sizeof(struct kprobe_trace_arg_ref));
541 if (ref == NULL)
542 return -ENOMEM;
437 if (*ref_ptr) 543 if (*ref_ptr)
438 (*ref_ptr)->next = ref; 544 (*ref_ptr)->next = ref;
439 else 545 else
440 *ref_ptr = ref; 546 *ref_ptr = ref;
441 } else { 547 } else {
442 /* Verify it is a data structure */ 548 /* Verify it is a data structure */
443 if (dwarf_tag(&type) != DW_TAG_structure_type) 549 if (dwarf_tag(&type) != DW_TAG_structure_type) {
444 die("%s is not a data structure.", varname); 550 pr_warning("%s is not a data structure.\n", varname);
445 551 return -EINVAL;
446 if (field->ref) 552 }
447 die("Semantic error: %s must be referred by '.'", 553 if (field->ref) {
448 field->name); 554 pr_err("Semantic error: %s must be referred by '.'\n",
449 if (!ref) 555 field->name);
450 die("Structure on a register is not supported yet."); 556 return -EINVAL;
557 }
558 if (!ref) {
559 pr_warning("Structure on a register is not "
560 "supported yet.\n");
561 return -ENOTSUP;
562 }
451 } 563 }
452 564
453 if (die_find_member(&type, field->name, &member) == NULL) 565 if (die_find_member(&type, field->name, die_mem) == NULL) {
454 die("%s(tyep:%s) has no member %s.", varname, 566 pr_warning("%s(tyep:%s) has no member %s.\n", varname,
455 dwarf_diename(&type), field->name); 567 dwarf_diename(&type), field->name);
568 return -EINVAL;
569 }
456 570
457 /* Get the offset of the field */ 571 /* Get the offset of the field */
458 if (dwarf_attr(&member, DW_AT_data_member_location, &attr) == NULL || 572 ret = die_get_data_member_location(die_mem, &offs);
459 dwarf_formudata(&attr, &offs) != 0) 573 if (ret < 0) {
460 die("Failed to get the offset of %s.", field->name); 574 pr_warning("Failed to get the offset of %s.\n", field->name);
575 return ret;
576 }
461 ref->offset += (long)offs; 577 ref->offset += (long)offs;
462 578
463 /* Converting next field */ 579 /* Converting next field */
464 if (field->next) 580 if (field->next)
465 convert_variable_fields(&member, field->name, field->next, 581 return convert_variable_fields(die_mem, field->name,
466 &ref); 582 field->next, &ref, die_mem);
583 else
584 return 0;
467} 585}
468 586
469/* Show a variables in kprobe event format */ 587/* Show a variables in kprobe event format */
470static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) 588static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
471{ 589{
472 Dwarf_Attribute attr; 590 Dwarf_Attribute attr;
591 Dwarf_Die die_mem;
473 Dwarf_Op *expr; 592 Dwarf_Op *expr;
474 size_t nexpr; 593 size_t nexpr;
475 int ret; 594 int ret;
@@ -481,44 +600,74 @@ static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
481 if (ret <= 0 || nexpr == 0) 600 if (ret <= 0 || nexpr == 0)
482 goto error; 601 goto error;
483 602
484 convert_location(expr, pf); 603 ret = convert_location(expr, pf);
485 604 if (ret == 0 && pf->pvar->field) {
486 if (pf->pvar->field) 605 ret = convert_variable_fields(vr_die, pf->pvar->var,
487 convert_variable_fields(vr_die, pf->pvar->name, 606 pf->pvar->field, &pf->tvar->ref,
488 pf->pvar->field, &pf->tvar->ref); 607 &die_mem);
608 vr_die = &die_mem;
609 }
610 if (ret == 0) {
611 if (pf->pvar->type) {
612 pf->tvar->type = strdup(pf->pvar->type);
613 if (pf->tvar->type == NULL)
614 ret = -ENOMEM;
615 } else
616 ret = convert_variable_type(vr_die, pf->tvar);
617 }
489 /* *expr will be cached in libdw. Don't free it. */ 618 /* *expr will be cached in libdw. Don't free it. */
490 return ; 619 return ret;
491error: 620error:
492 /* TODO: Support const_value */ 621 /* TODO: Support const_value */
493 die("Failed to find the location of %s at this address.\n" 622 pr_err("Failed to find the location of %s at this address.\n"
494 " Perhaps, it has been optimized out.", pf->pvar->name); 623 " Perhaps, it has been optimized out.\n", pf->pvar->var);
624 return -ENOENT;
495} 625}
496 626
497/* Find a variable in a subprogram die */ 627/* Find a variable in a subprogram die */
498static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) 628static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
499{ 629{
500 Dwarf_Die vr_die; 630 Dwarf_Die vr_die;
501 char buf[128]; 631 char buf[32], *ptr;
632 int ret;
633
634 /* TODO: Support arrays */
635 if (pf->pvar->name)
636 pf->tvar->name = strdup(pf->pvar->name);
637 else {
638 ret = synthesize_perf_probe_arg(pf->pvar, buf, 32);
639 if (ret < 0)
640 return ret;
641 ptr = strchr(buf, ':'); /* Change type separator to _ */
642 if (ptr)
643 *ptr = '_';
644 pf->tvar->name = strdup(buf);
645 }
646 if (pf->tvar->name == NULL)
647 return -ENOMEM;
502 648
503 /* TODO: Support struct members and arrays */ 649 if (!is_c_varname(pf->pvar->var)) {
504 if (!is_c_varname(pf->pvar->name)) {
505 /* Copy raw parameters */ 650 /* Copy raw parameters */
506 pf->tvar->value = xstrdup(pf->pvar->name); 651 pf->tvar->value = strdup(pf->pvar->var);
507 } else { 652 if (pf->tvar->value == NULL)
508 synthesize_perf_probe_arg(pf->pvar, buf, 128); 653 return -ENOMEM;
509 pf->tvar->name = xstrdup(buf); 654 else
510 pr_debug("Searching '%s' variable in context.\n", 655 return 0;
511 pf->pvar->name); 656 }
512 /* Search child die for local variables and parameters. */ 657
513 if (!die_find_variable(sp_die, pf->pvar->name, &vr_die)) 658 pr_debug("Searching '%s' variable in context.\n",
514 die("Failed to find '%s' in this function.", 659 pf->pvar->var);
515 pf->pvar->name); 660 /* Search child die for local variables and parameters. */
516 convert_variable(&vr_die, pf); 661 if (!die_find_variable(sp_die, pf->pvar->var, &vr_die)) {
662 pr_warning("Failed to find '%s' in this function.\n",
663 pf->pvar->var);
664 return -ENOENT;
517 } 665 }
666 return convert_variable(&vr_die, pf);
518} 667}
519 668
520/* Show a probe point to output buffer */ 669/* Show a probe point to output buffer */
521static void convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) 670static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
522{ 671{
523 struct kprobe_trace_event *tev; 672 struct kprobe_trace_event *tev;
524 Dwarf_Addr eaddr; 673 Dwarf_Addr eaddr;
@@ -528,23 +677,34 @@ static void convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
528 Dwarf_Attribute fb_attr; 677 Dwarf_Attribute fb_attr;
529 size_t nops; 678 size_t nops;
530 679
531 if (pf->ntevs == MAX_PROBES) 680 if (pf->ntevs == MAX_PROBES) {
532 die("Too many( > %d) probe point found.\n", MAX_PROBES); 681 pr_warning("Too many( > %d) probe point found.\n", MAX_PROBES);
682 return -ERANGE;
683 }
533 tev = &pf->tevs[pf->ntevs++]; 684 tev = &pf->tevs[pf->ntevs++];
534 685
535 /* If no real subprogram, find a real one */ 686 /* If no real subprogram, find a real one */
536 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) { 687 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
537 sp_die = die_find_real_subprogram(&pf->cu_die, 688 sp_die = die_find_real_subprogram(&pf->cu_die,
538 pf->addr, &die_mem); 689 pf->addr, &die_mem);
539 if (!sp_die) 690 if (!sp_die) {
540 die("Probe point is not found in subprograms."); 691 pr_warning("Failed to find probe point in any "
692 "functions.\n");
693 return -ENOENT;
694 }
541 } 695 }
542 696
543 /* Copy the name of probe point */ 697 /* Copy the name of probe point */
544 name = dwarf_diename(sp_die); 698 name = dwarf_diename(sp_die);
545 if (name) { 699 if (name) {
546 dwarf_entrypc(sp_die, &eaddr); 700 if (dwarf_entrypc(sp_die, &eaddr) != 0) {
547 tev->point.symbol = xstrdup(name); 701 pr_warning("Failed to get entry pc of %s\n",
702 dwarf_diename(sp_die));
703 return -ENOENT;
704 }
705 tev->point.symbol = strdup(name);
706 if (tev->point.symbol == NULL)
707 return -ENOMEM;
548 tev->point.offset = (unsigned long)(pf->addr - eaddr); 708 tev->point.offset = (unsigned long)(pf->addr - eaddr);
549 } else 709 } else
550 /* This function has no name. */ 710 /* This function has no name. */
@@ -556,55 +716,74 @@ static void convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
556 /* Get the frame base attribute/ops */ 716 /* Get the frame base attribute/ops */
557 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr); 717 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
558 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1); 718 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
559 if (ret <= 0 || nops == 0) 719 if (ret <= 0 || nops == 0) {
560 pf->fb_ops = NULL; 720 pf->fb_ops = NULL;
721 } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
722 pf->cfi != NULL) {
723 Dwarf_Frame *frame;
724 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
725 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
726 pr_warning("Failed to get CFA on 0x%jx\n",
727 (uintmax_t)pf->addr);
728 return -ENOENT;
729 }
730 }
561 731
562 /* Find each argument */ 732 /* Find each argument */
563 /* TODO: use dwarf_cfi_addrframe */
564 tev->nargs = pf->pev->nargs; 733 tev->nargs = pf->pev->nargs;
565 tev->args = xzalloc(sizeof(struct kprobe_trace_arg) * tev->nargs); 734 tev->args = zalloc(sizeof(struct kprobe_trace_arg) * tev->nargs);
735 if (tev->args == NULL)
736 return -ENOMEM;
566 for (i = 0; i < pf->pev->nargs; i++) { 737 for (i = 0; i < pf->pev->nargs; i++) {
567 pf->pvar = &pf->pev->args[i]; 738 pf->pvar = &pf->pev->args[i];
568 pf->tvar = &tev->args[i]; 739 pf->tvar = &tev->args[i];
569 find_variable(sp_die, pf); 740 ret = find_variable(sp_die, pf);
741 if (ret != 0)
742 return ret;
570 } 743 }
571 744
572 /* *pf->fb_ops will be cached in libdw. Don't free it. */ 745 /* *pf->fb_ops will be cached in libdw. Don't free it. */
573 pf->fb_ops = NULL; 746 pf->fb_ops = NULL;
747 return 0;
574} 748}
575 749
576/* Find probe point from its line number */ 750/* Find probe point from its line number */
577static void find_probe_point_by_line(struct probe_finder *pf) 751static int find_probe_point_by_line(struct probe_finder *pf)
578{ 752{
579 Dwarf_Lines *lines; 753 Dwarf_Lines *lines;
580 Dwarf_Line *line; 754 Dwarf_Line *line;
581 size_t nlines, i; 755 size_t nlines, i;
582 Dwarf_Addr addr; 756 Dwarf_Addr addr;
583 int lineno; 757 int lineno;
584 int ret; 758 int ret = 0;
585 759
586 ret = dwarf_getsrclines(&pf->cu_die, &lines, &nlines); 760 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
587 DIE_IF(ret != 0); 761 pr_warning("No source lines found in this CU.\n");
762 return -ENOENT;
763 }
588 764
589 for (i = 0; i < nlines; i++) { 765 for (i = 0; i < nlines && ret == 0; i++) {
590 line = dwarf_onesrcline(lines, i); 766 line = dwarf_onesrcline(lines, i);
591 dwarf_lineno(line, &lineno); 767 if (dwarf_lineno(line, &lineno) != 0 ||
592 if (lineno != pf->lno) 768 lineno != pf->lno)
593 continue; 769 continue;
594 770
595 /* TODO: Get fileno from line, but how? */ 771 /* TODO: Get fileno from line, but how? */
596 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0) 772 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
597 continue; 773 continue;
598 774
599 ret = dwarf_lineaddr(line, &addr); 775 if (dwarf_lineaddr(line, &addr) != 0) {
600 DIE_IF(ret != 0); 776 pr_warning("Failed to get the address of the line.\n");
777 return -ENOENT;
778 }
601 pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n", 779 pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
602 (int)i, lineno, (uintmax_t)addr); 780 (int)i, lineno, (uintmax_t)addr);
603 pf->addr = addr; 781 pf->addr = addr;
604 782
605 convert_probe_point(NULL, pf); 783 ret = convert_probe_point(NULL, pf);
606 /* Continuing, because target line might be inlined. */ 784 /* Continuing, because target line might be inlined. */
607 } 785 }
786 return ret;
608} 787}
609 788
610/* Find lines which match lazy pattern */ 789/* Find lines which match lazy pattern */
@@ -612,15 +791,27 @@ static int find_lazy_match_lines(struct list_head *head,
612 const char *fname, const char *pat) 791 const char *fname, const char *pat)
613{ 792{
614 char *fbuf, *p1, *p2; 793 char *fbuf, *p1, *p2;
615 int fd, line, nlines = 0; 794 int fd, ret, line, nlines = 0;
616 struct stat st; 795 struct stat st;
617 796
618 fd = open(fname, O_RDONLY); 797 fd = open(fname, O_RDONLY);
619 if (fd < 0) 798 if (fd < 0) {
620 die("failed to open %s", fname); 799 pr_warning("Failed to open %s: %s\n", fname, strerror(-fd));
621 DIE_IF(fstat(fd, &st) < 0); 800 return fd;
801 }
802
803 ret = fstat(fd, &st);
804 if (ret < 0) {
805 pr_warning("Failed to get the size of %s: %s\n",
806 fname, strerror(errno));
807 return ret;
808 }
622 fbuf = xmalloc(st.st_size + 2); 809 fbuf = xmalloc(st.st_size + 2);
623 DIE_IF(read(fd, fbuf, st.st_size) < 0); 810 ret = read(fd, fbuf, st.st_size);
811 if (ret < 0) {
812 pr_warning("Failed to read %s: %s\n", fname, strerror(errno));
813 return ret;
814 }
624 close(fd); 815 close(fd);
625 fbuf[st.st_size] = '\n'; /* Dummy line */ 816 fbuf[st.st_size] = '\n'; /* Dummy line */
626 fbuf[st.st_size + 1] = '\0'; 817 fbuf[st.st_size + 1] = '\0';
@@ -640,7 +831,7 @@ static int find_lazy_match_lines(struct list_head *head,
640} 831}
641 832
642/* Find probe points from lazy pattern */ 833/* Find probe points from lazy pattern */
643static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) 834static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
644{ 835{
645 Dwarf_Lines *lines; 836 Dwarf_Lines *lines;
646 Dwarf_Line *line; 837 Dwarf_Line *line;
@@ -648,31 +839,40 @@ static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
648 Dwarf_Addr addr; 839 Dwarf_Addr addr;
649 Dwarf_Die die_mem; 840 Dwarf_Die die_mem;
650 int lineno; 841 int lineno;
651 int ret; 842 int ret = 0;
652 843
653 if (list_empty(&pf->lcache)) { 844 if (list_empty(&pf->lcache)) {
654 /* Matching lazy line pattern */ 845 /* Matching lazy line pattern */
655 ret = find_lazy_match_lines(&pf->lcache, pf->fname, 846 ret = find_lazy_match_lines(&pf->lcache, pf->fname,
656 pf->pev->point.lazy_line); 847 pf->pev->point.lazy_line);
657 if (ret <= 0) 848 if (ret == 0) {
658 die("No matched lines found in %s.", pf->fname); 849 pr_debug("No matched lines found in %s.\n", pf->fname);
850 return 0;
851 } else if (ret < 0)
852 return ret;
659 } 853 }
660 854
661 ret = dwarf_getsrclines(&pf->cu_die, &lines, &nlines); 855 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
662 DIE_IF(ret != 0); 856 pr_warning("No source lines found in this CU.\n");
663 for (i = 0; i < nlines; i++) { 857 return -ENOENT;
858 }
859
860 for (i = 0; i < nlines && ret >= 0; i++) {
664 line = dwarf_onesrcline(lines, i); 861 line = dwarf_onesrcline(lines, i);
665 862
666 dwarf_lineno(line, &lineno); 863 if (dwarf_lineno(line, &lineno) != 0 ||
667 if (!line_list__has_line(&pf->lcache, lineno)) 864 !line_list__has_line(&pf->lcache, lineno))
668 continue; 865 continue;
669 866
670 /* TODO: Get fileno from line, but how? */ 867 /* TODO: Get fileno from line, but how? */
671 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0) 868 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
672 continue; 869 continue;
673 870
674 ret = dwarf_lineaddr(line, &addr); 871 if (dwarf_lineaddr(line, &addr) != 0) {
675 DIE_IF(ret != 0); 872 pr_debug("Failed to get the address of line %d.\n",
873 lineno);
874 continue;
875 }
676 if (sp_die) { 876 if (sp_die) {
677 /* Address filtering 1: does sp_die include addr? */ 877 /* Address filtering 1: does sp_die include addr? */
678 if (!dwarf_haspc(sp_die, addr)) 878 if (!dwarf_haspc(sp_die, addr))
@@ -686,27 +886,42 @@ static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
686 (int)i, lineno, (unsigned long long)addr); 886 (int)i, lineno, (unsigned long long)addr);
687 pf->addr = addr; 887 pf->addr = addr;
688 888
689 convert_probe_point(sp_die, pf); 889 ret = convert_probe_point(sp_die, pf);
690 /* Continuing, because target line might be inlined. */ 890 /* Continuing, because target line might be inlined. */
691 } 891 }
692 /* TODO: deallocate lines, but how? */ 892 /* TODO: deallocate lines, but how? */
893 return ret;
693} 894}
694 895
896/* Callback parameter with return value */
897struct dwarf_callback_param {
898 void *data;
899 int retval;
900};
901
695static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) 902static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
696{ 903{
697 struct probe_finder *pf = (struct probe_finder *)data; 904 struct dwarf_callback_param *param = data;
905 struct probe_finder *pf = param->data;
698 struct perf_probe_point *pp = &pf->pev->point; 906 struct perf_probe_point *pp = &pf->pev->point;
907 Dwarf_Addr addr;
699 908
700 if (pp->lazy_line) 909 if (pp->lazy_line)
701 find_probe_point_lazy(in_die, pf); 910 param->retval = find_probe_point_lazy(in_die, pf);
702 else { 911 else {
703 /* Get probe address */ 912 /* Get probe address */
704 pf->addr = die_get_entrypc(in_die); 913 if (dwarf_entrypc(in_die, &addr) != 0) {
914 pr_warning("Failed to get entry pc of %s.\n",
915 dwarf_diename(in_die));
916 param->retval = -ENOENT;
917 return DWARF_CB_ABORT;
918 }
919 pf->addr = addr;
705 pf->addr += pp->offset; 920 pf->addr += pp->offset;
706 pr_debug("found inline addr: 0x%jx\n", 921 pr_debug("found inline addr: 0x%jx\n",
707 (uintmax_t)pf->addr); 922 (uintmax_t)pf->addr);
708 923
709 convert_probe_point(in_die, pf); 924 param->retval = convert_probe_point(in_die, pf);
710 } 925 }
711 926
712 return DWARF_CB_OK; 927 return DWARF_CB_OK;
@@ -715,39 +930,53 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
715/* Search function from function name */ 930/* Search function from function name */
716static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) 931static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
717{ 932{
718 struct probe_finder *pf = (struct probe_finder *)data; 933 struct dwarf_callback_param *param = data;
934 struct probe_finder *pf = param->data;
719 struct perf_probe_point *pp = &pf->pev->point; 935 struct perf_probe_point *pp = &pf->pev->point;
720 936
721 /* Check tag and diename */ 937 /* Check tag and diename */
722 if (dwarf_tag(sp_die) != DW_TAG_subprogram || 938 if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
723 die_compare_name(sp_die, pp->function) != 0) 939 die_compare_name(sp_die, pp->function) != 0)
724 return 0; 940 return DWARF_CB_OK;
725 941
726 pf->fname = dwarf_decl_file(sp_die); 942 pf->fname = dwarf_decl_file(sp_die);
727 if (pp->line) { /* Function relative line */ 943 if (pp->line) { /* Function relative line */
728 dwarf_decl_line(sp_die, &pf->lno); 944 dwarf_decl_line(sp_die, &pf->lno);
729 pf->lno += pp->line; 945 pf->lno += pp->line;
730 find_probe_point_by_line(pf); 946 param->retval = find_probe_point_by_line(pf);
731 } else if (!dwarf_func_inline(sp_die)) { 947 } else if (!dwarf_func_inline(sp_die)) {
732 /* Real function */ 948 /* Real function */
733 if (pp->lazy_line) 949 if (pp->lazy_line)
734 find_probe_point_lazy(sp_die, pf); 950 param->retval = find_probe_point_lazy(sp_die, pf);
735 else { 951 else {
736 pf->addr = die_get_entrypc(sp_die); 952 if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
953 pr_warning("Failed to get entry pc of %s.\n",
954 dwarf_diename(sp_die));
955 param->retval = -ENOENT;
956 return DWARF_CB_ABORT;
957 }
737 pf->addr += pp->offset; 958 pf->addr += pp->offset;
738 /* TODO: Check the address in this function */ 959 /* TODO: Check the address in this function */
739 convert_probe_point(sp_die, pf); 960 param->retval = convert_probe_point(sp_die, pf);
740 } 961 }
741 } else 962 } else {
963 struct dwarf_callback_param _param = {.data = (void *)pf,
964 .retval = 0};
742 /* Inlined function: search instances */ 965 /* Inlined function: search instances */
743 dwarf_func_inline_instances(sp_die, probe_point_inline_cb, pf); 966 dwarf_func_inline_instances(sp_die, probe_point_inline_cb,
967 &_param);
968 param->retval = _param.retval;
969 }
744 970
745 return 1; /* Exit; no same symbol in this CU. */ 971 return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
746} 972}
747 973
748static void find_probe_point_by_func(struct probe_finder *pf) 974static int find_probe_point_by_func(struct probe_finder *pf)
749{ 975{
750 dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, pf, 0); 976 struct dwarf_callback_param _param = {.data = (void *)pf,
977 .retval = 0};
978 dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
979 return _param.retval;
751} 980}
752 981
753/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */ 982/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */
@@ -760,19 +989,29 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
760 size_t cuhl; 989 size_t cuhl;
761 Dwarf_Die *diep; 990 Dwarf_Die *diep;
762 Dwarf *dbg; 991 Dwarf *dbg;
992 int ret = 0;
763 993
764 pf.tevs = xzalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES); 994 pf.tevs = zalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES);
995 if (pf.tevs == NULL)
996 return -ENOMEM;
765 *tevs = pf.tevs; 997 *tevs = pf.tevs;
766 pf.ntevs = 0; 998 pf.ntevs = 0;
767 999
768 dbg = dwarf_begin(fd, DWARF_C_READ); 1000 dbg = dwarf_begin(fd, DWARF_C_READ);
769 if (!dbg) 1001 if (!dbg) {
770 return -ENOENT; 1002 pr_warning("No dwarf info found in the vmlinux - "
1003 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1004 return -EBADF;
1005 }
1006
1007 /* Get the call frame information from this dwarf */
1008 pf.cfi = dwarf_getcfi(dbg);
771 1009
772 off = 0; 1010 off = 0;
773 line_list__init(&pf.lcache); 1011 line_list__init(&pf.lcache);
774 /* Loop on CUs (Compilation Unit) */ 1012 /* Loop on CUs (Compilation Unit) */
775 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { 1013 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) &&
1014 ret >= 0) {
776 /* Get the DIE(Debugging Information Entry) of this CU */ 1015 /* Get the DIE(Debugging Information Entry) of this CU */
777 diep = dwarf_offdie(dbg, off + cuhl, &pf.cu_die); 1016 diep = dwarf_offdie(dbg, off + cuhl, &pf.cu_die);
778 if (!diep) 1017 if (!diep)
@@ -786,12 +1025,12 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
786 1025
787 if (!pp->file || pf.fname) { 1026 if (!pp->file || pf.fname) {
788 if (pp->function) 1027 if (pp->function)
789 find_probe_point_by_func(&pf); 1028 ret = find_probe_point_by_func(&pf);
790 else if (pp->lazy_line) 1029 else if (pp->lazy_line)
791 find_probe_point_lazy(NULL, &pf); 1030 ret = find_probe_point_lazy(NULL, &pf);
792 else { 1031 else {
793 pf.lno = pp->line; 1032 pf.lno = pp->line;
794 find_probe_point_by_line(&pf); 1033 ret = find_probe_point_by_line(&pf);
795 } 1034 }
796 } 1035 }
797 off = noff; 1036 off = noff;
@@ -799,7 +1038,7 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
799 line_list__free(&pf.lcache); 1038 line_list__free(&pf.lcache);
800 dwarf_end(dbg); 1039 dwarf_end(dbg);
801 1040
802 return pf.ntevs; 1041 return (ret < 0) ? ret : pf.ntevs;
803} 1042}
804 1043
805/* Reverse search */ 1044/* Reverse search */
@@ -812,10 +1051,11 @@ int find_perf_probe_point(int fd, unsigned long addr,
812 Dwarf_Addr laddr, eaddr; 1051 Dwarf_Addr laddr, eaddr;
813 const char *tmp; 1052 const char *tmp;
814 int lineno, ret = 0; 1053 int lineno, ret = 0;
1054 bool found = false;
815 1055
816 dbg = dwarf_begin(fd, DWARF_C_READ); 1056 dbg = dwarf_begin(fd, DWARF_C_READ);
817 if (!dbg) 1057 if (!dbg)
818 return -ENOENT; 1058 return -EBADF;
819 1059
820 /* Find cu die */ 1060 /* Find cu die */
821 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) { 1061 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) {
@@ -826,82 +1066,135 @@ int find_perf_probe_point(int fd, unsigned long addr,
826 /* Find a corresponding line */ 1066 /* Find a corresponding line */
827 line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr); 1067 line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr);
828 if (line) { 1068 if (line) {
829 dwarf_lineaddr(line, &laddr); 1069 if (dwarf_lineaddr(line, &laddr) == 0 &&
830 if ((Dwarf_Addr)addr == laddr) { 1070 (Dwarf_Addr)addr == laddr &&
831 dwarf_lineno(line, &lineno); 1071 dwarf_lineno(line, &lineno) == 0) {
832 ppt->line = lineno;
833
834 tmp = dwarf_linesrc(line, NULL, NULL); 1072 tmp = dwarf_linesrc(line, NULL, NULL);
835 DIE_IF(!tmp); 1073 if (tmp) {
836 ppt->file = xstrdup(tmp); 1074 ppt->line = lineno;
837 ret = 1; 1075 ppt->file = strdup(tmp);
1076 if (ppt->file == NULL) {
1077 ret = -ENOMEM;
1078 goto end;
1079 }
1080 found = true;
1081 }
838 } 1082 }
839 } 1083 }
840 1084
841 /* Find a corresponding function */ 1085 /* Find a corresponding function */
842 if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) { 1086 if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) {
843 tmp = dwarf_diename(&spdie); 1087 tmp = dwarf_diename(&spdie);
844 if (!tmp) 1088 if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0)
845 goto end; 1089 goto end;
846 1090
847 dwarf_entrypc(&spdie, &eaddr); 1091 if (ppt->line) {
848 if (!lineno) { 1092 if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
849 /* We don't have a line number, let's use offset */ 1093 &indie)) {
850 ppt->function = xstrdup(tmp); 1094 /* addr in an inline function */
851 ppt->offset = addr - (unsigned long)eaddr; 1095 tmp = dwarf_diename(&indie);
852 ret = 1; 1096 if (!tmp)
853 goto end; 1097 goto end;
1098 ret = dwarf_decl_line(&indie, &lineno);
1099 } else {
1100 if (eaddr == addr) { /* Function entry */
1101 lineno = ppt->line;
1102 ret = 0;
1103 } else
1104 ret = dwarf_decl_line(&spdie, &lineno);
1105 }
1106 if (ret == 0) {
1107 /* Make a relative line number */
1108 ppt->line -= lineno;
1109 goto found;
1110 }
854 } 1111 }
855 if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr, &indie)) { 1112 /* We don't have a line number, let's use offset */
856 /* addr in an inline function */ 1113 ppt->offset = addr - (unsigned long)eaddr;
857 tmp = dwarf_diename(&indie); 1114found:
858 if (!tmp) 1115 ppt->function = strdup(tmp);
859 goto end; 1116 if (ppt->function == NULL) {
860 dwarf_decl_line(&indie, &lineno); 1117 ret = -ENOMEM;
861 } else { 1118 goto end;
862 if (eaddr == addr) /* No offset: function entry */
863 lineno = ppt->line;
864 else
865 dwarf_decl_line(&spdie, &lineno);
866 } 1119 }
867 ppt->function = xstrdup(tmp); 1120 found = true;
868 ppt->line -= lineno; /* Make a relative line number */
869 } 1121 }
870 1122
871end: 1123end:
872 dwarf_end(dbg); 1124 dwarf_end(dbg);
1125 if (ret >= 0)
1126 ret = found ? 1 : 0;
873 return ret; 1127 return ret;
874} 1128}
875 1129
1130/* Add a line and store the src path */
1131static int line_range_add_line(const char *src, unsigned int lineno,
1132 struct line_range *lr)
1133{
1134 /* Copy real path */
1135 if (!lr->path) {
1136 lr->path = strdup(src);
1137 if (lr->path == NULL)
1138 return -ENOMEM;
1139 }
1140 return line_list__add_line(&lr->line_list, lineno);
1141}
1142
1143/* Search function declaration lines */
1144static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data)
1145{
1146 struct dwarf_callback_param *param = data;
1147 struct line_finder *lf = param->data;
1148 const char *src;
1149 int lineno;
1150
1151 src = dwarf_decl_file(sp_die);
1152 if (src && strtailcmp(src, lf->fname) != 0)
1153 return DWARF_CB_OK;
1154
1155 if (dwarf_decl_line(sp_die, &lineno) != 0 ||
1156 (lf->lno_s > lineno || lf->lno_e < lineno))
1157 return DWARF_CB_OK;
1158
1159 param->retval = line_range_add_line(src, lineno, lf->lr);
1160 return DWARF_CB_OK;
1161}
1162
1163static int find_line_range_func_decl_lines(struct line_finder *lf)
1164{
1165 struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
1166 dwarf_getfuncs(&lf->cu_die, line_range_funcdecl_cb, &param, 0);
1167 return param.retval;
1168}
876 1169
877/* Find line range from its line number */ 1170/* Find line range from its line number */
878static void find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) 1171static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
879{ 1172{
880 Dwarf_Lines *lines; 1173 Dwarf_Lines *lines;
881 Dwarf_Line *line; 1174 Dwarf_Line *line;
882 size_t nlines, i; 1175 size_t nlines, i;
883 Dwarf_Addr addr; 1176 Dwarf_Addr addr;
884 int lineno; 1177 int lineno, ret = 0;
885 int ret;
886 const char *src; 1178 const char *src;
887 Dwarf_Die die_mem; 1179 Dwarf_Die die_mem;
888 1180
889 line_list__init(&lf->lr->line_list); 1181 line_list__init(&lf->lr->line_list);
890 ret = dwarf_getsrclines(&lf->cu_die, &lines, &nlines); 1182 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
891 DIE_IF(ret != 0); 1183 pr_warning("No source lines found in this CU.\n");
1184 return -ENOENT;
1185 }
892 1186
1187 /* Search probable lines on lines list */
893 for (i = 0; i < nlines; i++) { 1188 for (i = 0; i < nlines; i++) {
894 line = dwarf_onesrcline(lines, i); 1189 line = dwarf_onesrcline(lines, i);
895 ret = dwarf_lineno(line, &lineno); 1190 if (dwarf_lineno(line, &lineno) != 0 ||
896 DIE_IF(ret != 0); 1191 (lf->lno_s > lineno || lf->lno_e < lineno))
897 if (lf->lno_s > lineno || lf->lno_e < lineno)
898 continue; 1192 continue;
899 1193
900 if (sp_die) { 1194 if (sp_die) {
901 /* Address filtering 1: does sp_die include addr? */ 1195 /* Address filtering 1: does sp_die include addr? */
902 ret = dwarf_lineaddr(line, &addr); 1196 if (dwarf_lineaddr(line, &addr) != 0 ||
903 DIE_IF(ret != 0); 1197 !dwarf_haspc(sp_die, addr))
904 if (!dwarf_haspc(sp_die, addr))
905 continue; 1198 continue;
906 1199
907 /* Address filtering 2: No child include addr? */ 1200 /* Address filtering 2: No child include addr? */
@@ -914,30 +1207,49 @@ static void find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
914 if (strtailcmp(src, lf->fname) != 0) 1207 if (strtailcmp(src, lf->fname) != 0)
915 continue; 1208 continue;
916 1209
917 /* Copy real path */ 1210 ret = line_range_add_line(src, lineno, lf->lr);
918 if (!lf->lr->path) 1211 if (ret < 0)
919 lf->lr->path = xstrdup(src); 1212 return ret;
920 line_list__add_line(&lf->lr->line_list, (unsigned int)lineno);
921 } 1213 }
1214
1215 /*
1216 * Dwarf lines doesn't include function declarations. We have to
1217 * check functions list or given function.
1218 */
1219 if (sp_die) {
1220 src = dwarf_decl_file(sp_die);
1221 if (src && dwarf_decl_line(sp_die, &lineno) == 0 &&
1222 (lf->lno_s <= lineno && lf->lno_e >= lineno))
1223 ret = line_range_add_line(src, lineno, lf->lr);
1224 } else
1225 ret = find_line_range_func_decl_lines(lf);
1226
922 /* Update status */ 1227 /* Update status */
923 if (!list_empty(&lf->lr->line_list)) 1228 if (ret >= 0)
924 lf->found = 1; 1229 if (!list_empty(&lf->lr->line_list))
1230 ret = lf->found = 1;
1231 else
1232 ret = 0; /* Lines are not found */
925 else { 1233 else {
926 free(lf->lr->path); 1234 free(lf->lr->path);
927 lf->lr->path = NULL; 1235 lf->lr->path = NULL;
928 } 1236 }
1237 return ret;
929} 1238}
930 1239
931static int line_range_inline_cb(Dwarf_Die *in_die, void *data) 1240static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
932{ 1241{
933 find_line_range_by_line(in_die, (struct line_finder *)data); 1242 struct dwarf_callback_param *param = data;
1243
1244 param->retval = find_line_range_by_line(in_die, param->data);
934 return DWARF_CB_ABORT; /* No need to find other instances */ 1245 return DWARF_CB_ABORT; /* No need to find other instances */
935} 1246}
936 1247
937/* Search function from function name */ 1248/* Search function from function name */
938static int line_range_search_cb(Dwarf_Die *sp_die, void *data) 1249static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
939{ 1250{
940 struct line_finder *lf = (struct line_finder *)data; 1251 struct dwarf_callback_param *param = data;
1252 struct line_finder *lf = param->data;
941 struct line_range *lr = lf->lr; 1253 struct line_range *lr = lf->lr;
942 1254
943 if (dwarf_tag(sp_die) == DW_TAG_subprogram && 1255 if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
@@ -946,44 +1258,55 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
946 dwarf_decl_line(sp_die, &lr->offset); 1258 dwarf_decl_line(sp_die, &lr->offset);
947 pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset); 1259 pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
948 lf->lno_s = lr->offset + lr->start; 1260 lf->lno_s = lr->offset + lr->start;
949 if (!lr->end) 1261 if (lf->lno_s < 0) /* Overflow */
1262 lf->lno_s = INT_MAX;
1263 lf->lno_e = lr->offset + lr->end;
1264 if (lf->lno_e < 0) /* Overflow */
950 lf->lno_e = INT_MAX; 1265 lf->lno_e = INT_MAX;
951 else 1266 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
952 lf->lno_e = lr->offset + lr->end;
953 lr->start = lf->lno_s; 1267 lr->start = lf->lno_s;
954 lr->end = lf->lno_e; 1268 lr->end = lf->lno_e;
955 if (dwarf_func_inline(sp_die)) 1269 if (dwarf_func_inline(sp_die)) {
1270 struct dwarf_callback_param _param;
1271 _param.data = (void *)lf;
1272 _param.retval = 0;
956 dwarf_func_inline_instances(sp_die, 1273 dwarf_func_inline_instances(sp_die,
957 line_range_inline_cb, lf); 1274 line_range_inline_cb,
958 else 1275 &_param);
959 find_line_range_by_line(sp_die, lf); 1276 param->retval = _param.retval;
960 return 1; 1277 } else
1278 param->retval = find_line_range_by_line(sp_die, lf);
1279 return DWARF_CB_ABORT;
961 } 1280 }
962 return 0; 1281 return DWARF_CB_OK;
963} 1282}
964 1283
965static void find_line_range_by_func(struct line_finder *lf) 1284static int find_line_range_by_func(struct line_finder *lf)
966{ 1285{
967 dwarf_getfuncs(&lf->cu_die, line_range_search_cb, lf, 0); 1286 struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
1287 dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
1288 return param.retval;
968} 1289}
969 1290
970int find_line_range(int fd, struct line_range *lr) 1291int find_line_range(int fd, struct line_range *lr)
971{ 1292{
972 struct line_finder lf = {.lr = lr, .found = 0}; 1293 struct line_finder lf = {.lr = lr, .found = 0};
973 int ret; 1294 int ret = 0;
974 Dwarf_Off off = 0, noff; 1295 Dwarf_Off off = 0, noff;
975 size_t cuhl; 1296 size_t cuhl;
976 Dwarf_Die *diep; 1297 Dwarf_Die *diep;
977 Dwarf *dbg; 1298 Dwarf *dbg;
978 1299
979 dbg = dwarf_begin(fd, DWARF_C_READ); 1300 dbg = dwarf_begin(fd, DWARF_C_READ);
980 if (!dbg) 1301 if (!dbg) {
981 return -ENOENT; 1302 pr_warning("No dwarf info found in the vmlinux - "
1303 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1304 return -EBADF;
1305 }
982 1306
983 /* Loop on CUs (Compilation Unit) */ 1307 /* Loop on CUs (Compilation Unit) */
984 while (!lf.found) { 1308 while (!lf.found && ret >= 0) {
985 ret = dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL); 1309 if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0)
986 if (ret != 0)
987 break; 1310 break;
988 1311
989 /* Get the DIE(Debugging Information Entry) of this CU */ 1312 /* Get the DIE(Debugging Information Entry) of this CU */
@@ -999,20 +1322,18 @@ int find_line_range(int fd, struct line_range *lr)
999 1322
1000 if (!lr->file || lf.fname) { 1323 if (!lr->file || lf.fname) {
1001 if (lr->function) 1324 if (lr->function)
1002 find_line_range_by_func(&lf); 1325 ret = find_line_range_by_func(&lf);
1003 else { 1326 else {
1004 lf.lno_s = lr->start; 1327 lf.lno_s = lr->start;
1005 if (!lr->end) 1328 lf.lno_e = lr->end;
1006 lf.lno_e = INT_MAX; 1329 ret = find_line_range_by_line(NULL, &lf);
1007 else
1008 lf.lno_e = lr->end;
1009 find_line_range_by_line(NULL, &lf);
1010 } 1330 }
1011 } 1331 }
1012 off = noff; 1332 off = noff;
1013 } 1333 }
1014 pr_debug("path: %lx\n", (unsigned long)lr->path); 1334 pr_debug("path: %lx\n", (unsigned long)lr->path);
1015 dwarf_end(dbg); 1335 dwarf_end(dbg);
1016 return lf.found; 1336
1337 return (ret < 0) ? ret : lf.found;
1017} 1338}
1018 1339
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 2a271321944f..310ce897229c 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -42,6 +42,7 @@ struct probe_finder {
42 struct list_head lcache; /* Line cache for lazy match */ 42 struct list_head lcache; /* Line cache for lazy match */
43 43
44 /* For variable searching */ 44 /* For variable searching */
45 Dwarf_CFI *cfi; /* Call Frame Information */
45 Dwarf_Op *fb_ops; /* Frame base attribute */ 46 Dwarf_Op *fb_ops; /* Frame base attribute */
46 struct perf_probe_arg *pvar; /* Current target variable */ 47 struct perf_probe_arg *pvar; /* Current target variable */
47 struct kprobe_trace_arg *tvar; /* Current result variable */ 48 struct kprobe_trace_arg *tvar; /* Current result variable */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 9d24d4b2c8fb..da30b305fba0 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -30,38 +30,38 @@ static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf,
30 size_t size, unsigned int width); 30 size_t size, unsigned int width);
31 31
32struct sort_entry sort_thread = { 32struct sort_entry sort_thread = {
33 .header = "Command: Pid", 33 .se_header = "Command: Pid",
34 .cmp = sort__thread_cmp, 34 .se_cmp = sort__thread_cmp,
35 .snprintf = hist_entry__thread_snprintf, 35 .se_snprintf = hist_entry__thread_snprintf,
36 .width = &threads__col_width, 36 .se_width = &threads__col_width,
37}; 37};
38 38
39struct sort_entry sort_comm = { 39struct sort_entry sort_comm = {
40 .header = "Command", 40 .se_header = "Command",
41 .cmp = sort__comm_cmp, 41 .se_cmp = sort__comm_cmp,
42 .collapse = sort__comm_collapse, 42 .se_collapse = sort__comm_collapse,
43 .snprintf = hist_entry__comm_snprintf, 43 .se_snprintf = hist_entry__comm_snprintf,
44 .width = &comms__col_width, 44 .se_width = &comms__col_width,
45}; 45};
46 46
47struct sort_entry sort_dso = { 47struct sort_entry sort_dso = {
48 .header = "Shared Object", 48 .se_header = "Shared Object",
49 .cmp = sort__dso_cmp, 49 .se_cmp = sort__dso_cmp,
50 .snprintf = hist_entry__dso_snprintf, 50 .se_snprintf = hist_entry__dso_snprintf,
51 .width = &dsos__col_width, 51 .se_width = &dsos__col_width,
52}; 52};
53 53
54struct sort_entry sort_sym = { 54struct sort_entry sort_sym = {
55 .header = "Symbol", 55 .se_header = "Symbol",
56 .cmp = sort__sym_cmp, 56 .se_cmp = sort__sym_cmp,
57 .snprintf = hist_entry__sym_snprintf, 57 .se_snprintf = hist_entry__sym_snprintf,
58}; 58};
59 59
60struct sort_entry sort_parent = { 60struct sort_entry sort_parent = {
61 .header = "Parent symbol", 61 .se_header = "Parent symbol",
62 .cmp = sort__parent_cmp, 62 .se_cmp = sort__parent_cmp,
63 .snprintf = hist_entry__parent_snprintf, 63 .se_snprintf = hist_entry__parent_snprintf,
64 .width = &parent_symbol__col_width, 64 .se_width = &parent_symbol__col_width,
65}; 65};
66 66
67struct sort_dimension { 67struct sort_dimension {
@@ -255,7 +255,7 @@ int sort_dimension__add(const char *tok)
255 if (strncasecmp(tok, sd->name, strlen(tok))) 255 if (strncasecmp(tok, sd->name, strlen(tok)))
256 continue; 256 continue;
257 257
258 if (sd->entry->collapse) 258 if (sd->entry->se_collapse)
259 sort__need_collapse = 1; 259 sort__need_collapse = 1;
260 260
261 if (sd->entry == &sort_parent) { 261 if (sd->entry == &sort_parent) {
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 6d7b4be70609..1d857aa2c01f 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -78,13 +78,13 @@ enum sort_type {
78struct sort_entry { 78struct sort_entry {
79 struct list_head list; 79 struct list_head list;
80 80
81 const char *header; 81 const char *se_header;
82 82
83 int64_t (*cmp)(struct hist_entry *, struct hist_entry *); 83 int64_t (*se_cmp)(struct hist_entry *, struct hist_entry *);
84 int64_t (*collapse)(struct hist_entry *, struct hist_entry *); 84 int64_t (*se_collapse)(struct hist_entry *, struct hist_entry *);
85 int (*snprintf)(struct hist_entry *self, char *bf, size_t size, 85 int (*se_snprintf)(struct hist_entry *self, char *bf, size_t size,
86 unsigned int width); 86 unsigned int width);
87 unsigned int *width; 87 unsigned int *se_width;
88 bool elide; 88 bool elide;
89}; 89};
90 90