Commit ed9eb845d7916b2bc863e5b93c82e18be8faf032

Authored by Ingo Molnar

Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/g…

…it/acme/linux into perf/urgent

Pull perf/urgent fixes from Arnaldo Carvalho de Melo:

"
  - 'perf probe' should fall back to find probe point in symbols when failing
    to do so in a debuginfo file (Masami Hiramatsu)

  - Fix 'perf probe' crash in dwarf_getcfi_elf (Namhyung Kim)

  - Fix shell completion with 'perf list' --raw-dump option (Taesoo Kim)

  - Fix 'perf diff' to sort by baseline field by default (Namhyung Kim)
"

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>

Showing 4 changed files Inline Diff

tools/perf/builtin-diff.c
1 /* 1 /*
2 * builtin-diff.c 2 * builtin-diff.c
3 * 3 *
4 * Builtin diff command: Analyze two perf.data input files, look up and read 4 * Builtin diff command: Analyze two perf.data input files, look up and read
5 * DSOs and symbol information, sort them and produce a diff. 5 * DSOs and symbol information, sort them and produce a diff.
6 */ 6 */
7 #include "builtin.h" 7 #include "builtin.h"
8 8
9 #include "util/debug.h" 9 #include "util/debug.h"
10 #include "util/event.h" 10 #include "util/event.h"
11 #include "util/hist.h" 11 #include "util/hist.h"
12 #include "util/evsel.h" 12 #include "util/evsel.h"
13 #include "util/evlist.h" 13 #include "util/evlist.h"
14 #include "util/session.h" 14 #include "util/session.h"
15 #include "util/tool.h" 15 #include "util/tool.h"
16 #include "util/sort.h" 16 #include "util/sort.h"
17 #include "util/symbol.h" 17 #include "util/symbol.h"
18 #include "util/util.h" 18 #include "util/util.h"
19 #include "util/data.h" 19 #include "util/data.h"
20 20
21 #include <stdlib.h> 21 #include <stdlib.h>
22 #include <math.h> 22 #include <math.h>
23 23
24 /* Diff command specific HPP columns. */ 24 /* Diff command specific HPP columns. */
25 enum { 25 enum {
26 PERF_HPP_DIFF__BASELINE, 26 PERF_HPP_DIFF__BASELINE,
27 PERF_HPP_DIFF__PERIOD, 27 PERF_HPP_DIFF__PERIOD,
28 PERF_HPP_DIFF__PERIOD_BASELINE, 28 PERF_HPP_DIFF__PERIOD_BASELINE,
29 PERF_HPP_DIFF__DELTA, 29 PERF_HPP_DIFF__DELTA,
30 PERF_HPP_DIFF__RATIO, 30 PERF_HPP_DIFF__RATIO,
31 PERF_HPP_DIFF__WEIGHTED_DIFF, 31 PERF_HPP_DIFF__WEIGHTED_DIFF,
32 PERF_HPP_DIFF__FORMULA, 32 PERF_HPP_DIFF__FORMULA,
33 33
34 PERF_HPP_DIFF__MAX_INDEX 34 PERF_HPP_DIFF__MAX_INDEX
35 }; 35 };
36 36
37 struct diff_hpp_fmt { 37 struct diff_hpp_fmt {
38 struct perf_hpp_fmt fmt; 38 struct perf_hpp_fmt fmt;
39 int idx; 39 int idx;
40 char *header; 40 char *header;
41 int header_width; 41 int header_width;
42 }; 42 };
43 43
44 struct data__file { 44 struct data__file {
45 struct perf_session *session; 45 struct perf_session *session;
46 struct perf_data_file file; 46 struct perf_data_file file;
47 int idx; 47 int idx;
48 struct hists *hists; 48 struct hists *hists;
49 struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX]; 49 struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX];
50 }; 50 };
51 51
52 static struct data__file *data__files; 52 static struct data__file *data__files;
53 static int data__files_cnt; 53 static int data__files_cnt;
54 54
55 #define data__for_each_file_start(i, d, s) \ 55 #define data__for_each_file_start(i, d, s) \
56 for (i = s, d = &data__files[s]; \ 56 for (i = s, d = &data__files[s]; \
57 i < data__files_cnt; \ 57 i < data__files_cnt; \
58 i++, d = &data__files[i]) 58 i++, d = &data__files[i])
59 59
60 #define data__for_each_file(i, d) data__for_each_file_start(i, d, 0) 60 #define data__for_each_file(i, d) data__for_each_file_start(i, d, 0)
61 #define data__for_each_file_new(i, d) data__for_each_file_start(i, d, 1) 61 #define data__for_each_file_new(i, d) data__for_each_file_start(i, d, 1)
62 62
63 static bool force; 63 static bool force;
64 static bool show_period; 64 static bool show_period;
65 static bool show_formula; 65 static bool show_formula;
66 static bool show_baseline_only; 66 static bool show_baseline_only;
67 static unsigned int sort_compute; 67 static unsigned int sort_compute;
68 68
69 static s64 compute_wdiff_w1; 69 static s64 compute_wdiff_w1;
70 static s64 compute_wdiff_w2; 70 static s64 compute_wdiff_w2;
71 71
72 enum { 72 enum {
73 COMPUTE_DELTA, 73 COMPUTE_DELTA,
74 COMPUTE_RATIO, 74 COMPUTE_RATIO,
75 COMPUTE_WEIGHTED_DIFF, 75 COMPUTE_WEIGHTED_DIFF,
76 COMPUTE_MAX, 76 COMPUTE_MAX,
77 }; 77 };
78 78
79 const char *compute_names[COMPUTE_MAX] = { 79 const char *compute_names[COMPUTE_MAX] = {
80 [COMPUTE_DELTA] = "delta", 80 [COMPUTE_DELTA] = "delta",
81 [COMPUTE_RATIO] = "ratio", 81 [COMPUTE_RATIO] = "ratio",
82 [COMPUTE_WEIGHTED_DIFF] = "wdiff", 82 [COMPUTE_WEIGHTED_DIFF] = "wdiff",
83 }; 83 };
84 84
85 static int compute; 85 static int compute;
86 86
87 static int compute_2_hpp[COMPUTE_MAX] = { 87 static int compute_2_hpp[COMPUTE_MAX] = {
88 [COMPUTE_DELTA] = PERF_HPP_DIFF__DELTA, 88 [COMPUTE_DELTA] = PERF_HPP_DIFF__DELTA,
89 [COMPUTE_RATIO] = PERF_HPP_DIFF__RATIO, 89 [COMPUTE_RATIO] = PERF_HPP_DIFF__RATIO,
90 [COMPUTE_WEIGHTED_DIFF] = PERF_HPP_DIFF__WEIGHTED_DIFF, 90 [COMPUTE_WEIGHTED_DIFF] = PERF_HPP_DIFF__WEIGHTED_DIFF,
91 }; 91 };
92 92
93 #define MAX_COL_WIDTH 70 93 #define MAX_COL_WIDTH 70
94 94
95 static struct header_column { 95 static struct header_column {
96 const char *name; 96 const char *name;
97 int width; 97 int width;
98 } columns[PERF_HPP_DIFF__MAX_INDEX] = { 98 } columns[PERF_HPP_DIFF__MAX_INDEX] = {
99 [PERF_HPP_DIFF__BASELINE] = { 99 [PERF_HPP_DIFF__BASELINE] = {
100 .name = "Baseline", 100 .name = "Baseline",
101 }, 101 },
102 [PERF_HPP_DIFF__PERIOD] = { 102 [PERF_HPP_DIFF__PERIOD] = {
103 .name = "Period", 103 .name = "Period",
104 .width = 14, 104 .width = 14,
105 }, 105 },
106 [PERF_HPP_DIFF__PERIOD_BASELINE] = { 106 [PERF_HPP_DIFF__PERIOD_BASELINE] = {
107 .name = "Base period", 107 .name = "Base period",
108 .width = 14, 108 .width = 14,
109 }, 109 },
110 [PERF_HPP_DIFF__DELTA] = { 110 [PERF_HPP_DIFF__DELTA] = {
111 .name = "Delta", 111 .name = "Delta",
112 .width = 7, 112 .width = 7,
113 }, 113 },
114 [PERF_HPP_DIFF__RATIO] = { 114 [PERF_HPP_DIFF__RATIO] = {
115 .name = "Ratio", 115 .name = "Ratio",
116 .width = 14, 116 .width = 14,
117 }, 117 },
118 [PERF_HPP_DIFF__WEIGHTED_DIFF] = { 118 [PERF_HPP_DIFF__WEIGHTED_DIFF] = {
119 .name = "Weighted diff", 119 .name = "Weighted diff",
120 .width = 14, 120 .width = 14,
121 }, 121 },
122 [PERF_HPP_DIFF__FORMULA] = { 122 [PERF_HPP_DIFF__FORMULA] = {
123 .name = "Formula", 123 .name = "Formula",
124 .width = MAX_COL_WIDTH, 124 .width = MAX_COL_WIDTH,
125 } 125 }
126 }; 126 };
127 127
128 static int setup_compute_opt_wdiff(char *opt) 128 static int setup_compute_opt_wdiff(char *opt)
129 { 129 {
130 char *w1_str = opt; 130 char *w1_str = opt;
131 char *w2_str; 131 char *w2_str;
132 132
133 int ret = -EINVAL; 133 int ret = -EINVAL;
134 134
135 if (!opt) 135 if (!opt)
136 goto out; 136 goto out;
137 137
138 w2_str = strchr(opt, ','); 138 w2_str = strchr(opt, ',');
139 if (!w2_str) 139 if (!w2_str)
140 goto out; 140 goto out;
141 141
142 *w2_str++ = 0x0; 142 *w2_str++ = 0x0;
143 if (!*w2_str) 143 if (!*w2_str)
144 goto out; 144 goto out;
145 145
146 compute_wdiff_w1 = strtol(w1_str, NULL, 10); 146 compute_wdiff_w1 = strtol(w1_str, NULL, 10);
147 compute_wdiff_w2 = strtol(w2_str, NULL, 10); 147 compute_wdiff_w2 = strtol(w2_str, NULL, 10);
148 148
149 if (!compute_wdiff_w1 || !compute_wdiff_w2) 149 if (!compute_wdiff_w1 || !compute_wdiff_w2)
150 goto out; 150 goto out;
151 151
152 pr_debug("compute wdiff w1(%" PRId64 ") w2(%" PRId64 ")\n", 152 pr_debug("compute wdiff w1(%" PRId64 ") w2(%" PRId64 ")\n",
153 compute_wdiff_w1, compute_wdiff_w2); 153 compute_wdiff_w1, compute_wdiff_w2);
154 154
155 ret = 0; 155 ret = 0;
156 156
157 out: 157 out:
158 if (ret) 158 if (ret)
159 pr_err("Failed: wrong weight data, use 'wdiff:w1,w2'\n"); 159 pr_err("Failed: wrong weight data, use 'wdiff:w1,w2'\n");
160 160
161 return ret; 161 return ret;
162 } 162 }
163 163
164 static int setup_compute_opt(char *opt) 164 static int setup_compute_opt(char *opt)
165 { 165 {
166 if (compute == COMPUTE_WEIGHTED_DIFF) 166 if (compute == COMPUTE_WEIGHTED_DIFF)
167 return setup_compute_opt_wdiff(opt); 167 return setup_compute_opt_wdiff(opt);
168 168
169 if (opt) { 169 if (opt) {
170 pr_err("Failed: extra option specified '%s'", opt); 170 pr_err("Failed: extra option specified '%s'", opt);
171 return -EINVAL; 171 return -EINVAL;
172 } 172 }
173 173
174 return 0; 174 return 0;
175 } 175 }
176 176
177 static int setup_compute(const struct option *opt, const char *str, 177 static int setup_compute(const struct option *opt, const char *str,
178 int unset __maybe_unused) 178 int unset __maybe_unused)
179 { 179 {
180 int *cp = (int *) opt->value; 180 int *cp = (int *) opt->value;
181 char *cstr = (char *) str; 181 char *cstr = (char *) str;
182 char buf[50]; 182 char buf[50];
183 unsigned i; 183 unsigned i;
184 char *option; 184 char *option;
185 185
186 if (!str) { 186 if (!str) {
187 *cp = COMPUTE_DELTA; 187 *cp = COMPUTE_DELTA;
188 return 0; 188 return 0;
189 } 189 }
190 190
191 option = strchr(str, ':'); 191 option = strchr(str, ':');
192 if (option) { 192 if (option) {
193 unsigned len = option++ - str; 193 unsigned len = option++ - str;
194 194
195 /* 195 /*
196 * The str data are not writeable, so we need 196 * The str data are not writeable, so we need
197 * to use another buffer. 197 * to use another buffer.
198 */ 198 */
199 199
200 /* No option value is longer. */ 200 /* No option value is longer. */
201 if (len >= sizeof(buf)) 201 if (len >= sizeof(buf))
202 return -EINVAL; 202 return -EINVAL;
203 203
204 strncpy(buf, str, len); 204 strncpy(buf, str, len);
205 buf[len] = 0x0; 205 buf[len] = 0x0;
206 cstr = buf; 206 cstr = buf;
207 } 207 }
208 208
209 for (i = 0; i < COMPUTE_MAX; i++) 209 for (i = 0; i < COMPUTE_MAX; i++)
210 if (!strcmp(cstr, compute_names[i])) { 210 if (!strcmp(cstr, compute_names[i])) {
211 *cp = i; 211 *cp = i;
212 return setup_compute_opt(option); 212 return setup_compute_opt(option);
213 } 213 }
214 214
215 pr_err("Failed: '%s' is not computation method " 215 pr_err("Failed: '%s' is not computation method "
216 "(use 'delta','ratio' or 'wdiff')\n", str); 216 "(use 'delta','ratio' or 'wdiff')\n", str);
217 return -EINVAL; 217 return -EINVAL;
218 } 218 }
219 219
220 static double period_percent(struct hist_entry *he, u64 period) 220 static double period_percent(struct hist_entry *he, u64 period)
221 { 221 {
222 u64 total = hists__total_period(he->hists); 222 u64 total = hists__total_period(he->hists);
223 223
224 return (period * 100.0) / total; 224 return (period * 100.0) / total;
225 } 225 }
226 226
227 static double compute_delta(struct hist_entry *he, struct hist_entry *pair) 227 static double compute_delta(struct hist_entry *he, struct hist_entry *pair)
228 { 228 {
229 double old_percent = period_percent(he, he->stat.period); 229 double old_percent = period_percent(he, he->stat.period);
230 double new_percent = period_percent(pair, pair->stat.period); 230 double new_percent = period_percent(pair, pair->stat.period);
231 231
232 pair->diff.period_ratio_delta = new_percent - old_percent; 232 pair->diff.period_ratio_delta = new_percent - old_percent;
233 pair->diff.computed = true; 233 pair->diff.computed = true;
234 return pair->diff.period_ratio_delta; 234 return pair->diff.period_ratio_delta;
235 } 235 }
236 236
237 static double compute_ratio(struct hist_entry *he, struct hist_entry *pair) 237 static double compute_ratio(struct hist_entry *he, struct hist_entry *pair)
238 { 238 {
239 double old_period = he->stat.period ?: 1; 239 double old_period = he->stat.period ?: 1;
240 double new_period = pair->stat.period; 240 double new_period = pair->stat.period;
241 241
242 pair->diff.computed = true; 242 pair->diff.computed = true;
243 pair->diff.period_ratio = new_period / old_period; 243 pair->diff.period_ratio = new_period / old_period;
244 return pair->diff.period_ratio; 244 return pair->diff.period_ratio;
245 } 245 }
246 246
247 static s64 compute_wdiff(struct hist_entry *he, struct hist_entry *pair) 247 static s64 compute_wdiff(struct hist_entry *he, struct hist_entry *pair)
248 { 248 {
249 u64 old_period = he->stat.period; 249 u64 old_period = he->stat.period;
250 u64 new_period = pair->stat.period; 250 u64 new_period = pair->stat.period;
251 251
252 pair->diff.computed = true; 252 pair->diff.computed = true;
253 pair->diff.wdiff = new_period * compute_wdiff_w2 - 253 pair->diff.wdiff = new_period * compute_wdiff_w2 -
254 old_period * compute_wdiff_w1; 254 old_period * compute_wdiff_w1;
255 255
256 return pair->diff.wdiff; 256 return pair->diff.wdiff;
257 } 257 }
258 258
259 static int formula_delta(struct hist_entry *he, struct hist_entry *pair, 259 static int formula_delta(struct hist_entry *he, struct hist_entry *pair,
260 char *buf, size_t size) 260 char *buf, size_t size)
261 { 261 {
262 u64 he_total = he->hists->stats.total_period; 262 u64 he_total = he->hists->stats.total_period;
263 u64 pair_total = pair->hists->stats.total_period; 263 u64 pair_total = pair->hists->stats.total_period;
264 264
265 if (symbol_conf.filter_relative) { 265 if (symbol_conf.filter_relative) {
266 he_total = he->hists->stats.total_non_filtered_period; 266 he_total = he->hists->stats.total_non_filtered_period;
267 pair_total = pair->hists->stats.total_non_filtered_period; 267 pair_total = pair->hists->stats.total_non_filtered_period;
268 } 268 }
269 return scnprintf(buf, size, 269 return scnprintf(buf, size,
270 "(%" PRIu64 " * 100 / %" PRIu64 ") - " 270 "(%" PRIu64 " * 100 / %" PRIu64 ") - "
271 "(%" PRIu64 " * 100 / %" PRIu64 ")", 271 "(%" PRIu64 " * 100 / %" PRIu64 ")",
272 pair->stat.period, pair_total, 272 pair->stat.period, pair_total,
273 he->stat.period, he_total); 273 he->stat.period, he_total);
274 } 274 }
275 275
276 static int formula_ratio(struct hist_entry *he, struct hist_entry *pair, 276 static int formula_ratio(struct hist_entry *he, struct hist_entry *pair,
277 char *buf, size_t size) 277 char *buf, size_t size)
278 { 278 {
279 double old_period = he->stat.period; 279 double old_period = he->stat.period;
280 double new_period = pair->stat.period; 280 double new_period = pair->stat.period;
281 281
282 return scnprintf(buf, size, "%.0F / %.0F", new_period, old_period); 282 return scnprintf(buf, size, "%.0F / %.0F", new_period, old_period);
283 } 283 }
284 284
285 static int formula_wdiff(struct hist_entry *he, struct hist_entry *pair, 285 static int formula_wdiff(struct hist_entry *he, struct hist_entry *pair,
286 char *buf, size_t size) 286 char *buf, size_t size)
287 { 287 {
288 u64 old_period = he->stat.period; 288 u64 old_period = he->stat.period;
289 u64 new_period = pair->stat.period; 289 u64 new_period = pair->stat.period;
290 290
291 return scnprintf(buf, size, 291 return scnprintf(buf, size,
292 "(%" PRIu64 " * " "%" PRId64 ") - (%" PRIu64 " * " "%" PRId64 ")", 292 "(%" PRIu64 " * " "%" PRId64 ") - (%" PRIu64 " * " "%" PRId64 ")",
293 new_period, compute_wdiff_w2, old_period, compute_wdiff_w1); 293 new_period, compute_wdiff_w2, old_period, compute_wdiff_w1);
294 } 294 }
295 295
296 static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair, 296 static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair,
297 char *buf, size_t size) 297 char *buf, size_t size)
298 { 298 {
299 switch (compute) { 299 switch (compute) {
300 case COMPUTE_DELTA: 300 case COMPUTE_DELTA:
301 return formula_delta(he, pair, buf, size); 301 return formula_delta(he, pair, buf, size);
302 case COMPUTE_RATIO: 302 case COMPUTE_RATIO:
303 return formula_ratio(he, pair, buf, size); 303 return formula_ratio(he, pair, buf, size);
304 case COMPUTE_WEIGHTED_DIFF: 304 case COMPUTE_WEIGHTED_DIFF:
305 return formula_wdiff(he, pair, buf, size); 305 return formula_wdiff(he, pair, buf, size);
306 default: 306 default:
307 BUG_ON(1); 307 BUG_ON(1);
308 } 308 }
309 309
310 return -1; 310 return -1;
311 } 311 }
312 312
313 static int hists__add_entry(struct hists *hists, 313 static int hists__add_entry(struct hists *hists,
314 struct addr_location *al, u64 period, 314 struct addr_location *al, u64 period,
315 u64 weight, u64 transaction) 315 u64 weight, u64 transaction)
316 { 316 {
317 if (__hists__add_entry(hists, al, NULL, NULL, NULL, period, weight, 317 if (__hists__add_entry(hists, al, NULL, NULL, NULL, period, weight,
318 transaction, true) != NULL) 318 transaction, true) != NULL)
319 return 0; 319 return 0;
320 return -ENOMEM; 320 return -ENOMEM;
321 } 321 }
322 322
323 static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, 323 static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
324 union perf_event *event, 324 union perf_event *event,
325 struct perf_sample *sample, 325 struct perf_sample *sample,
326 struct perf_evsel *evsel, 326 struct perf_evsel *evsel,
327 struct machine *machine) 327 struct machine *machine)
328 { 328 {
329 struct addr_location al; 329 struct addr_location al;
330 struct hists *hists = evsel__hists(evsel); 330 struct hists *hists = evsel__hists(evsel);
331 331
332 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { 332 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
333 pr_warning("problem processing %d event, skipping it.\n", 333 pr_warning("problem processing %d event, skipping it.\n",
334 event->header.type); 334 event->header.type);
335 return -1; 335 return -1;
336 } 336 }
337 337
338 if (hists__add_entry(hists, &al, sample->period, 338 if (hists__add_entry(hists, &al, sample->period,
339 sample->weight, sample->transaction)) { 339 sample->weight, sample->transaction)) {
340 pr_warning("problem incrementing symbol period, skipping event\n"); 340 pr_warning("problem incrementing symbol period, skipping event\n");
341 return -1; 341 return -1;
342 } 342 }
343 343
344 /* 344 /*
345 * The total_period is updated here before going to the output 345 * The total_period is updated here before going to the output
346 * tree since normally only the baseline hists will call 346 * tree since normally only the baseline hists will call
347 * hists__output_resort() and precompute needs the total 347 * hists__output_resort() and precompute needs the total
348 * period in order to sort entries by percentage delta. 348 * period in order to sort entries by percentage delta.
349 */ 349 */
350 hists->stats.total_period += sample->period; 350 hists->stats.total_period += sample->period;
351 if (!al.filtered) 351 if (!al.filtered)
352 hists->stats.total_non_filtered_period += sample->period; 352 hists->stats.total_non_filtered_period += sample->period;
353 353
354 return 0; 354 return 0;
355 } 355 }
356 356
357 static struct perf_tool tool = { 357 static struct perf_tool tool = {
358 .sample = diff__process_sample_event, 358 .sample = diff__process_sample_event,
359 .mmap = perf_event__process_mmap, 359 .mmap = perf_event__process_mmap,
360 .mmap2 = perf_event__process_mmap2, 360 .mmap2 = perf_event__process_mmap2,
361 .comm = perf_event__process_comm, 361 .comm = perf_event__process_comm,
362 .exit = perf_event__process_exit, 362 .exit = perf_event__process_exit,
363 .fork = perf_event__process_fork, 363 .fork = perf_event__process_fork,
364 .lost = perf_event__process_lost, 364 .lost = perf_event__process_lost,
365 .ordered_events = true, 365 .ordered_events = true,
366 .ordering_requires_timestamps = true, 366 .ordering_requires_timestamps = true,
367 }; 367 };
368 368
369 static struct perf_evsel *evsel_match(struct perf_evsel *evsel, 369 static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
370 struct perf_evlist *evlist) 370 struct perf_evlist *evlist)
371 { 371 {
372 struct perf_evsel *e; 372 struct perf_evsel *e;
373 373
374 evlist__for_each(evlist, e) { 374 evlist__for_each(evlist, e) {
375 if (perf_evsel__match2(evsel, e)) 375 if (perf_evsel__match2(evsel, e))
376 return e; 376 return e;
377 } 377 }
378 378
379 return NULL; 379 return NULL;
380 } 380 }
381 381
382 static void perf_evlist__collapse_resort(struct perf_evlist *evlist) 382 static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
383 { 383 {
384 struct perf_evsel *evsel; 384 struct perf_evsel *evsel;
385 385
386 evlist__for_each(evlist, evsel) { 386 evlist__for_each(evlist, evsel) {
387 struct hists *hists = evsel__hists(evsel); 387 struct hists *hists = evsel__hists(evsel);
388 388
389 hists__collapse_resort(hists, NULL); 389 hists__collapse_resort(hists, NULL);
390 } 390 }
391 } 391 }
392 392
393 static struct hist_entry* 393 static struct hist_entry*
394 get_pair_data(struct hist_entry *he, struct data__file *d) 394 get_pair_data(struct hist_entry *he, struct data__file *d)
395 { 395 {
396 if (hist_entry__has_pairs(he)) { 396 if (hist_entry__has_pairs(he)) {
397 struct hist_entry *pair; 397 struct hist_entry *pair;
398 398
399 list_for_each_entry(pair, &he->pairs.head, pairs.node) 399 list_for_each_entry(pair, &he->pairs.head, pairs.node)
400 if (pair->hists == d->hists) 400 if (pair->hists == d->hists)
401 return pair; 401 return pair;
402 } 402 }
403 403
404 return NULL; 404 return NULL;
405 } 405 }
406 406
407 static struct hist_entry* 407 static struct hist_entry*
408 get_pair_fmt(struct hist_entry *he, struct diff_hpp_fmt *dfmt) 408 get_pair_fmt(struct hist_entry *he, struct diff_hpp_fmt *dfmt)
409 { 409 {
410 void *ptr = dfmt - dfmt->idx; 410 void *ptr = dfmt - dfmt->idx;
411 struct data__file *d = container_of(ptr, struct data__file, fmt); 411 struct data__file *d = container_of(ptr, struct data__file, fmt);
412 412
413 return get_pair_data(he, d); 413 return get_pair_data(he, d);
414 } 414 }
415 415
416 static void hists__baseline_only(struct hists *hists) 416 static void hists__baseline_only(struct hists *hists)
417 { 417 {
418 struct rb_root *root; 418 struct rb_root *root;
419 struct rb_node *next; 419 struct rb_node *next;
420 420
421 if (sort__need_collapse) 421 if (sort__need_collapse)
422 root = &hists->entries_collapsed; 422 root = &hists->entries_collapsed;
423 else 423 else
424 root = hists->entries_in; 424 root = hists->entries_in;
425 425
426 next = rb_first(root); 426 next = rb_first(root);
427 while (next != NULL) { 427 while (next != NULL) {
428 struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node_in); 428 struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node_in);
429 429
430 next = rb_next(&he->rb_node_in); 430 next = rb_next(&he->rb_node_in);
431 if (!hist_entry__next_pair(he)) { 431 if (!hist_entry__next_pair(he)) {
432 rb_erase(&he->rb_node_in, root); 432 rb_erase(&he->rb_node_in, root);
433 hist_entry__free(he); 433 hist_entry__free(he);
434 } 434 }
435 } 435 }
436 } 436 }
437 437
438 static void hists__precompute(struct hists *hists) 438 static void hists__precompute(struct hists *hists)
439 { 439 {
440 struct rb_root *root; 440 struct rb_root *root;
441 struct rb_node *next; 441 struct rb_node *next;
442 442
443 if (sort__need_collapse) 443 if (sort__need_collapse)
444 root = &hists->entries_collapsed; 444 root = &hists->entries_collapsed;
445 else 445 else
446 root = hists->entries_in; 446 root = hists->entries_in;
447 447
448 next = rb_first(root); 448 next = rb_first(root);
449 while (next != NULL) { 449 while (next != NULL) {
450 struct hist_entry *he, *pair; 450 struct hist_entry *he, *pair;
451 451
452 he = rb_entry(next, struct hist_entry, rb_node_in); 452 he = rb_entry(next, struct hist_entry, rb_node_in);
453 next = rb_next(&he->rb_node_in); 453 next = rb_next(&he->rb_node_in);
454 454
455 pair = get_pair_data(he, &data__files[sort_compute]); 455 pair = get_pair_data(he, &data__files[sort_compute]);
456 if (!pair) 456 if (!pair)
457 continue; 457 continue;
458 458
459 switch (compute) { 459 switch (compute) {
460 case COMPUTE_DELTA: 460 case COMPUTE_DELTA:
461 compute_delta(he, pair); 461 compute_delta(he, pair);
462 break; 462 break;
463 case COMPUTE_RATIO: 463 case COMPUTE_RATIO:
464 compute_ratio(he, pair); 464 compute_ratio(he, pair);
465 break; 465 break;
466 case COMPUTE_WEIGHTED_DIFF: 466 case COMPUTE_WEIGHTED_DIFF:
467 compute_wdiff(he, pair); 467 compute_wdiff(he, pair);
468 break; 468 break;
469 default: 469 default:
470 BUG_ON(1); 470 BUG_ON(1);
471 } 471 }
472 } 472 }
473 } 473 }
474 474
475 static int64_t cmp_doubles(double l, double r) 475 static int64_t cmp_doubles(double l, double r)
476 { 476 {
477 if (l > r) 477 if (l > r)
478 return -1; 478 return -1;
479 else if (l < r) 479 else if (l < r)
480 return 1; 480 return 1;
481 else 481 else
482 return 0; 482 return 0;
483 } 483 }
484 484
485 static int64_t 485 static int64_t
486 __hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, 486 __hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
487 int c) 487 int c)
488 { 488 {
489 switch (c) { 489 switch (c) {
490 case COMPUTE_DELTA: 490 case COMPUTE_DELTA:
491 { 491 {
492 double l = left->diff.period_ratio_delta; 492 double l = left->diff.period_ratio_delta;
493 double r = right->diff.period_ratio_delta; 493 double r = right->diff.period_ratio_delta;
494 494
495 return cmp_doubles(l, r); 495 return cmp_doubles(l, r);
496 } 496 }
497 case COMPUTE_RATIO: 497 case COMPUTE_RATIO:
498 { 498 {
499 double l = left->diff.period_ratio; 499 double l = left->diff.period_ratio;
500 double r = right->diff.period_ratio; 500 double r = right->diff.period_ratio;
501 501
502 return cmp_doubles(l, r); 502 return cmp_doubles(l, r);
503 } 503 }
504 case COMPUTE_WEIGHTED_DIFF: 504 case COMPUTE_WEIGHTED_DIFF:
505 { 505 {
506 s64 l = left->diff.wdiff; 506 s64 l = left->diff.wdiff;
507 s64 r = right->diff.wdiff; 507 s64 r = right->diff.wdiff;
508 508
509 return r - l; 509 return r - l;
510 } 510 }
511 default: 511 default:
512 BUG_ON(1); 512 BUG_ON(1);
513 } 513 }
514 514
515 return 0; 515 return 0;
516 } 516 }
517 517
518 static int64_t 518 static int64_t
519 hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, 519 hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
520 int c) 520 int c)
521 { 521 {
522 bool pairs_left = hist_entry__has_pairs(left); 522 bool pairs_left = hist_entry__has_pairs(left);
523 bool pairs_right = hist_entry__has_pairs(right); 523 bool pairs_right = hist_entry__has_pairs(right);
524 struct hist_entry *p_right, *p_left; 524 struct hist_entry *p_right, *p_left;
525 525
526 if (!pairs_left && !pairs_right) 526 if (!pairs_left && !pairs_right)
527 return 0; 527 return 0;
528 528
529 if (!pairs_left || !pairs_right) 529 if (!pairs_left || !pairs_right)
530 return pairs_left ? -1 : 1; 530 return pairs_left ? -1 : 1;
531 531
532 p_left = get_pair_data(left, &data__files[sort_compute]); 532 p_left = get_pair_data(left, &data__files[sort_compute]);
533 p_right = get_pair_data(right, &data__files[sort_compute]); 533 p_right = get_pair_data(right, &data__files[sort_compute]);
534 534
535 if (!p_left && !p_right) 535 if (!p_left && !p_right)
536 return 0; 536 return 0;
537 537
538 if (!p_left || !p_right) 538 if (!p_left || !p_right)
539 return p_left ? -1 : 1; 539 return p_left ? -1 : 1;
540 540
541 /* 541 /*
542 * We have 2 entries of same kind, let's 542 * We have 2 entries of same kind, let's
543 * make the data comparison. 543 * make the data comparison.
544 */ 544 */
545 return __hist_entry__cmp_compute(p_left, p_right, c); 545 return __hist_entry__cmp_compute(p_left, p_right, c);
546 } 546 }
547 547
548 static int64_t
549 hist_entry__cmp_nop(struct hist_entry *left __maybe_unused,
550 struct hist_entry *right __maybe_unused)
551 {
552 return 0;
553 }
554
555 static int64_t
556 hist_entry__cmp_baseline(struct hist_entry *left, struct hist_entry *right)
557 {
558 if (sort_compute)
559 return 0;
560
561 if (left->stat.period == right->stat.period)
562 return 0;
563 return left->stat.period > right->stat.period ? 1 : -1;
564 }
565
566 static int64_t
567 hist_entry__cmp_delta(struct hist_entry *left, struct hist_entry *right)
568 {
569 return hist_entry__cmp_compute(right, left, COMPUTE_DELTA);
570 }
571
572 static int64_t
573 hist_entry__cmp_ratio(struct hist_entry *left, struct hist_entry *right)
574 {
575 return hist_entry__cmp_compute(right, left, COMPUTE_RATIO);
576 }
577
578 static int64_t
579 hist_entry__cmp_wdiff(struct hist_entry *left, struct hist_entry *right)
580 {
581 return hist_entry__cmp_compute(right, left, COMPUTE_WEIGHTED_DIFF);
582 }
583
548 static void insert_hist_entry_by_compute(struct rb_root *root, 584 static void insert_hist_entry_by_compute(struct rb_root *root,
549 struct hist_entry *he, 585 struct hist_entry *he,
550 int c) 586 int c)
551 { 587 {
552 struct rb_node **p = &root->rb_node; 588 struct rb_node **p = &root->rb_node;
553 struct rb_node *parent = NULL; 589 struct rb_node *parent = NULL;
554 struct hist_entry *iter; 590 struct hist_entry *iter;
555 591
556 while (*p != NULL) { 592 while (*p != NULL) {
557 parent = *p; 593 parent = *p;
558 iter = rb_entry(parent, struct hist_entry, rb_node); 594 iter = rb_entry(parent, struct hist_entry, rb_node);
559 if (hist_entry__cmp_compute(he, iter, c) < 0) 595 if (hist_entry__cmp_compute(he, iter, c) < 0)
560 p = &(*p)->rb_left; 596 p = &(*p)->rb_left;
561 else 597 else
562 p = &(*p)->rb_right; 598 p = &(*p)->rb_right;
563 } 599 }
564 600
565 rb_link_node(&he->rb_node, parent, p); 601 rb_link_node(&he->rb_node, parent, p);
566 rb_insert_color(&he->rb_node, root); 602 rb_insert_color(&he->rb_node, root);
567 } 603 }
568 604
569 static void hists__compute_resort(struct hists *hists) 605 static void hists__compute_resort(struct hists *hists)
570 { 606 {
571 struct rb_root *root; 607 struct rb_root *root;
572 struct rb_node *next; 608 struct rb_node *next;
573 609
574 if (sort__need_collapse) 610 if (sort__need_collapse)
575 root = &hists->entries_collapsed; 611 root = &hists->entries_collapsed;
576 else 612 else
577 root = hists->entries_in; 613 root = hists->entries_in;
578 614
579 hists->entries = RB_ROOT; 615 hists->entries = RB_ROOT;
580 next = rb_first(root); 616 next = rb_first(root);
581 617
582 hists__reset_stats(hists); 618 hists__reset_stats(hists);
583 hists__reset_col_len(hists); 619 hists__reset_col_len(hists);
584 620
585 while (next != NULL) { 621 while (next != NULL) {
586 struct hist_entry *he; 622 struct hist_entry *he;
587 623
588 he = rb_entry(next, struct hist_entry, rb_node_in); 624 he = rb_entry(next, struct hist_entry, rb_node_in);
589 next = rb_next(&he->rb_node_in); 625 next = rb_next(&he->rb_node_in);
590 626
591 insert_hist_entry_by_compute(&hists->entries, he, compute); 627 insert_hist_entry_by_compute(&hists->entries, he, compute);
592 hists__inc_stats(hists, he); 628 hists__inc_stats(hists, he);
593 629
594 if (!he->filtered) 630 if (!he->filtered)
595 hists__calc_col_len(hists, he); 631 hists__calc_col_len(hists, he);
596 } 632 }
597 } 633 }
598 634
599 static void hists__process(struct hists *hists) 635 static void hists__process(struct hists *hists)
600 { 636 {
601 if (show_baseline_only) 637 if (show_baseline_only)
602 hists__baseline_only(hists); 638 hists__baseline_only(hists);
603 639
604 if (sort_compute) { 640 if (sort_compute) {
605 hists__precompute(hists); 641 hists__precompute(hists);
606 hists__compute_resort(hists); 642 hists__compute_resort(hists);
607 } else { 643 } else {
608 hists__output_resort(hists, NULL); 644 hists__output_resort(hists, NULL);
609 } 645 }
610 646
611 hists__fprintf(hists, true, 0, 0, 0, stdout); 647 hists__fprintf(hists, true, 0, 0, 0, stdout);
612 } 648 }
613 649
614 static void data__fprintf(void) 650 static void data__fprintf(void)
615 { 651 {
616 struct data__file *d; 652 struct data__file *d;
617 int i; 653 int i;
618 654
619 fprintf(stdout, "# Data files:\n"); 655 fprintf(stdout, "# Data files:\n");
620 656
621 data__for_each_file(i, d) 657 data__for_each_file(i, d)
622 fprintf(stdout, "# [%d] %s %s\n", 658 fprintf(stdout, "# [%d] %s %s\n",
623 d->idx, d->file.path, 659 d->idx, d->file.path,
624 !d->idx ? "(Baseline)" : ""); 660 !d->idx ? "(Baseline)" : "");
625 661
626 fprintf(stdout, "#\n"); 662 fprintf(stdout, "#\n");
627 } 663 }
628 664
629 static void data_process(void) 665 static void data_process(void)
630 { 666 {
631 struct perf_evlist *evlist_base = data__files[0].session->evlist; 667 struct perf_evlist *evlist_base = data__files[0].session->evlist;
632 struct perf_evsel *evsel_base; 668 struct perf_evsel *evsel_base;
633 bool first = true; 669 bool first = true;
634 670
635 evlist__for_each(evlist_base, evsel_base) { 671 evlist__for_each(evlist_base, evsel_base) {
636 struct hists *hists_base = evsel__hists(evsel_base); 672 struct hists *hists_base = evsel__hists(evsel_base);
637 struct data__file *d; 673 struct data__file *d;
638 int i; 674 int i;
639 675
640 data__for_each_file_new(i, d) { 676 data__for_each_file_new(i, d) {
641 struct perf_evlist *evlist = d->session->evlist; 677 struct perf_evlist *evlist = d->session->evlist;
642 struct perf_evsel *evsel; 678 struct perf_evsel *evsel;
643 struct hists *hists; 679 struct hists *hists;
644 680
645 evsel = evsel_match(evsel_base, evlist); 681 evsel = evsel_match(evsel_base, evlist);
646 if (!evsel) 682 if (!evsel)
647 continue; 683 continue;
648 684
649 hists = evsel__hists(evsel); 685 hists = evsel__hists(evsel);
650 d->hists = hists; 686 d->hists = hists;
651 687
652 hists__match(hists_base, hists); 688 hists__match(hists_base, hists);
653 689
654 if (!show_baseline_only) 690 if (!show_baseline_only)
655 hists__link(hists_base, hists); 691 hists__link(hists_base, hists);
656 } 692 }
657 693
658 fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n", 694 fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n",
659 perf_evsel__name(evsel_base)); 695 perf_evsel__name(evsel_base));
660 696
661 first = false; 697 first = false;
662 698
663 if (verbose || data__files_cnt > 2) 699 if (verbose || data__files_cnt > 2)
664 data__fprintf(); 700 data__fprintf();
665 701
666 hists__process(hists_base); 702 hists__process(hists_base);
667 } 703 }
668 } 704 }
669 705
670 static void data__free(struct data__file *d) 706 static void data__free(struct data__file *d)
671 { 707 {
672 int col; 708 int col;
673 709
674 for (col = 0; col < PERF_HPP_DIFF__MAX_INDEX; col++) { 710 for (col = 0; col < PERF_HPP_DIFF__MAX_INDEX; col++) {
675 struct diff_hpp_fmt *fmt = &d->fmt[col]; 711 struct diff_hpp_fmt *fmt = &d->fmt[col];
676 712
677 zfree(&fmt->header); 713 zfree(&fmt->header);
678 } 714 }
679 } 715 }
680 716
681 static int __cmd_diff(void) 717 static int __cmd_diff(void)
682 { 718 {
683 struct data__file *d; 719 struct data__file *d;
684 int ret = -EINVAL, i; 720 int ret = -EINVAL, i;
685 721
686 data__for_each_file(i, d) { 722 data__for_each_file(i, d) {
687 d->session = perf_session__new(&d->file, false, &tool); 723 d->session = perf_session__new(&d->file, false, &tool);
688 if (!d->session) { 724 if (!d->session) {
689 pr_err("Failed to open %s\n", d->file.path); 725 pr_err("Failed to open %s\n", d->file.path);
690 ret = -1; 726 ret = -1;
691 goto out_delete; 727 goto out_delete;
692 } 728 }
693 729
694 ret = perf_session__process_events(d->session, &tool); 730 ret = perf_session__process_events(d->session, &tool);
695 if (ret) { 731 if (ret) {
696 pr_err("Failed to process %s\n", d->file.path); 732 pr_err("Failed to process %s\n", d->file.path);
697 goto out_delete; 733 goto out_delete;
698 } 734 }
699 735
700 perf_evlist__collapse_resort(d->session->evlist); 736 perf_evlist__collapse_resort(d->session->evlist);
701 } 737 }
702 738
703 data_process(); 739 data_process();
704 740
705 out_delete: 741 out_delete:
706 data__for_each_file(i, d) { 742 data__for_each_file(i, d) {
707 if (d->session) 743 if (d->session)
708 perf_session__delete(d->session); 744 perf_session__delete(d->session);
709 745
710 data__free(d); 746 data__free(d);
711 } 747 }
712 748
713 free(data__files); 749 free(data__files);
714 return ret; 750 return ret;
715 } 751 }
716 752
717 static const char * const diff_usage[] = { 753 static const char * const diff_usage[] = {
718 "perf diff [<options>] [old_file] [new_file]", 754 "perf diff [<options>] [old_file] [new_file]",
719 NULL, 755 NULL,
720 }; 756 };
721 757
722 static const struct option options[] = { 758 static const struct option options[] = {
723 OPT_INCR('v', "verbose", &verbose, 759 OPT_INCR('v', "verbose", &verbose,
724 "be more verbose (show symbol address, etc)"), 760 "be more verbose (show symbol address, etc)"),
725 OPT_BOOLEAN('b', "baseline-only", &show_baseline_only, 761 OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
726 "Show only items with match in baseline"), 762 "Show only items with match in baseline"),
727 OPT_CALLBACK('c', "compute", &compute, 763 OPT_CALLBACK('c', "compute", &compute,
728 "delta,ratio,wdiff:w1,w2 (default delta)", 764 "delta,ratio,wdiff:w1,w2 (default delta)",
729 "Entries differential computation selection", 765 "Entries differential computation selection",
730 setup_compute), 766 setup_compute),
731 OPT_BOOLEAN('p', "period", &show_period, 767 OPT_BOOLEAN('p', "period", &show_period,
732 "Show period values."), 768 "Show period values."),
733 OPT_BOOLEAN('F', "formula", &show_formula, 769 OPT_BOOLEAN('F', "formula", &show_formula,
734 "Show formula."), 770 "Show formula."),
735 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 771 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
736 "dump raw trace in ASCII"), 772 "dump raw trace in ASCII"),
737 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 773 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
738 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 774 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
739 "load module symbols - WARNING: use only with -k and LIVE kernel"), 775 "load module symbols - WARNING: use only with -k and LIVE kernel"),
740 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 776 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
741 "only consider symbols in these dsos"), 777 "only consider symbols in these dsos"),
742 OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", 778 OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
743 "only consider symbols in these comms"), 779 "only consider symbols in these comms"),
744 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 780 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
745 "only consider these symbols"), 781 "only consider these symbols"),
746 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 782 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
747 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..." 783 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..."
748 " Please refer the man page for the complete list."), 784 " Please refer the man page for the complete list."),
749 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator", 785 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
750 "separator for columns, no spaces will be added between " 786 "separator for columns, no spaces will be added between "
751 "columns '.' is reserved."), 787 "columns '.' is reserved."),
752 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 788 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
753 "Look for files with symbols relative to this directory"), 789 "Look for files with symbols relative to this directory"),
754 OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."), 790 OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."),
755 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", 791 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
756 "How to display percentage of filtered entries", parse_filter_percentage), 792 "How to display percentage of filtered entries", parse_filter_percentage),
757 OPT_END() 793 OPT_END()
758 }; 794 };
759 795
760 static double baseline_percent(struct hist_entry *he) 796 static double baseline_percent(struct hist_entry *he)
761 { 797 {
762 u64 total = hists__total_period(he->hists); 798 u64 total = hists__total_period(he->hists);
763 799
764 return 100.0 * he->stat.period / total; 800 return 100.0 * he->stat.period / total;
765 } 801 }
766 802
767 static int hpp__color_baseline(struct perf_hpp_fmt *fmt, 803 static int hpp__color_baseline(struct perf_hpp_fmt *fmt,
768 struct perf_hpp *hpp, struct hist_entry *he) 804 struct perf_hpp *hpp, struct hist_entry *he)
769 { 805 {
770 struct diff_hpp_fmt *dfmt = 806 struct diff_hpp_fmt *dfmt =
771 container_of(fmt, struct diff_hpp_fmt, fmt); 807 container_of(fmt, struct diff_hpp_fmt, fmt);
772 double percent = baseline_percent(he); 808 double percent = baseline_percent(he);
773 char pfmt[20] = " "; 809 char pfmt[20] = " ";
774 810
775 if (!he->dummy) { 811 if (!he->dummy) {
776 scnprintf(pfmt, 20, "%%%d.2f%%%%", dfmt->header_width - 1); 812 scnprintf(pfmt, 20, "%%%d.2f%%%%", dfmt->header_width - 1);
777 return percent_color_snprintf(hpp->buf, hpp->size, 813 return percent_color_snprintf(hpp->buf, hpp->size,
778 pfmt, percent); 814 pfmt, percent);
779 } else 815 } else
780 return scnprintf(hpp->buf, hpp->size, "%*s", 816 return scnprintf(hpp->buf, hpp->size, "%*s",
781 dfmt->header_width, pfmt); 817 dfmt->header_width, pfmt);
782 } 818 }
783 819
784 static int hpp__entry_baseline(struct hist_entry *he, char *buf, size_t size) 820 static int hpp__entry_baseline(struct hist_entry *he, char *buf, size_t size)
785 { 821 {
786 double percent = baseline_percent(he); 822 double percent = baseline_percent(he);
787 const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; 823 const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
788 int ret = 0; 824 int ret = 0;
789 825
790 if (!he->dummy) 826 if (!he->dummy)
791 ret = scnprintf(buf, size, fmt, percent); 827 ret = scnprintf(buf, size, fmt, percent);
792 828
793 return ret; 829 return ret;
794 } 830 }
795 831
796 static int __hpp__color_compare(struct perf_hpp_fmt *fmt, 832 static int __hpp__color_compare(struct perf_hpp_fmt *fmt,
797 struct perf_hpp *hpp, struct hist_entry *he, 833 struct perf_hpp *hpp, struct hist_entry *he,
798 int comparison_method) 834 int comparison_method)
799 { 835 {
800 struct diff_hpp_fmt *dfmt = 836 struct diff_hpp_fmt *dfmt =
801 container_of(fmt, struct diff_hpp_fmt, fmt); 837 container_of(fmt, struct diff_hpp_fmt, fmt);
802 struct hist_entry *pair = get_pair_fmt(he, dfmt); 838 struct hist_entry *pair = get_pair_fmt(he, dfmt);
803 double diff; 839 double diff;
804 s64 wdiff; 840 s64 wdiff;
805 char pfmt[20] = " "; 841 char pfmt[20] = " ";
806 842
807 if (!pair) 843 if (!pair)
808 goto dummy_print; 844 goto dummy_print;
809 845
810 switch (comparison_method) { 846 switch (comparison_method) {
811 case COMPUTE_DELTA: 847 case COMPUTE_DELTA:
812 if (pair->diff.computed) 848 if (pair->diff.computed)
813 diff = pair->diff.period_ratio_delta; 849 diff = pair->diff.period_ratio_delta;
814 else 850 else
815 diff = compute_delta(he, pair); 851 diff = compute_delta(he, pair);
816 852
817 if (fabs(diff) < 0.01) 853 if (fabs(diff) < 0.01)
818 goto dummy_print; 854 goto dummy_print;
819 scnprintf(pfmt, 20, "%%%+d.2f%%%%", dfmt->header_width - 1); 855 scnprintf(pfmt, 20, "%%%+d.2f%%%%", dfmt->header_width - 1);
820 return percent_color_snprintf(hpp->buf, hpp->size, 856 return percent_color_snprintf(hpp->buf, hpp->size,
821 pfmt, diff); 857 pfmt, diff);
822 case COMPUTE_RATIO: 858 case COMPUTE_RATIO:
823 if (he->dummy) 859 if (he->dummy)
824 goto dummy_print; 860 goto dummy_print;
825 if (pair->diff.computed) 861 if (pair->diff.computed)
826 diff = pair->diff.period_ratio; 862 diff = pair->diff.period_ratio;
827 else 863 else
828 diff = compute_ratio(he, pair); 864 diff = compute_ratio(he, pair);
829 865
830 scnprintf(pfmt, 20, "%%%d.6f", dfmt->header_width); 866 scnprintf(pfmt, 20, "%%%d.6f", dfmt->header_width);
831 return value_color_snprintf(hpp->buf, hpp->size, 867 return value_color_snprintf(hpp->buf, hpp->size,
832 pfmt, diff); 868 pfmt, diff);
833 case COMPUTE_WEIGHTED_DIFF: 869 case COMPUTE_WEIGHTED_DIFF:
834 if (he->dummy) 870 if (he->dummy)
835 goto dummy_print; 871 goto dummy_print;
836 if (pair->diff.computed) 872 if (pair->diff.computed)
837 wdiff = pair->diff.wdiff; 873 wdiff = pair->diff.wdiff;
838 else 874 else
839 wdiff = compute_wdiff(he, pair); 875 wdiff = compute_wdiff(he, pair);
840 876
841 scnprintf(pfmt, 20, "%%14ld", dfmt->header_width); 877 scnprintf(pfmt, 20, "%%14ld", dfmt->header_width);
842 return color_snprintf(hpp->buf, hpp->size, 878 return color_snprintf(hpp->buf, hpp->size,
843 get_percent_color(wdiff), 879 get_percent_color(wdiff),
844 pfmt, wdiff); 880 pfmt, wdiff);
845 default: 881 default:
846 BUG_ON(1); 882 BUG_ON(1);
847 } 883 }
848 dummy_print: 884 dummy_print:
849 return scnprintf(hpp->buf, hpp->size, "%*s", 885 return scnprintf(hpp->buf, hpp->size, "%*s",
850 dfmt->header_width, pfmt); 886 dfmt->header_width, pfmt);
851 } 887 }
852 888
853 static int hpp__color_delta(struct perf_hpp_fmt *fmt, 889 static int hpp__color_delta(struct perf_hpp_fmt *fmt,
854 struct perf_hpp *hpp, struct hist_entry *he) 890 struct perf_hpp *hpp, struct hist_entry *he)
855 { 891 {
856 return __hpp__color_compare(fmt, hpp, he, COMPUTE_DELTA); 892 return __hpp__color_compare(fmt, hpp, he, COMPUTE_DELTA);
857 } 893 }
858 894
859 static int hpp__color_ratio(struct perf_hpp_fmt *fmt, 895 static int hpp__color_ratio(struct perf_hpp_fmt *fmt,
860 struct perf_hpp *hpp, struct hist_entry *he) 896 struct perf_hpp *hpp, struct hist_entry *he)
861 { 897 {
862 return __hpp__color_compare(fmt, hpp, he, COMPUTE_RATIO); 898 return __hpp__color_compare(fmt, hpp, he, COMPUTE_RATIO);
863 } 899 }
864 900
865 static int hpp__color_wdiff(struct perf_hpp_fmt *fmt, 901 static int hpp__color_wdiff(struct perf_hpp_fmt *fmt,
866 struct perf_hpp *hpp, struct hist_entry *he) 902 struct perf_hpp *hpp, struct hist_entry *he)
867 { 903 {
868 return __hpp__color_compare(fmt, hpp, he, COMPUTE_WEIGHTED_DIFF); 904 return __hpp__color_compare(fmt, hpp, he, COMPUTE_WEIGHTED_DIFF);
869 } 905 }
870 906
871 static void 907 static void
872 hpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size) 908 hpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size)
873 { 909 {
874 switch (idx) { 910 switch (idx) {
875 case PERF_HPP_DIFF__PERIOD_BASELINE: 911 case PERF_HPP_DIFF__PERIOD_BASELINE:
876 scnprintf(buf, size, "%" PRIu64, he->stat.period); 912 scnprintf(buf, size, "%" PRIu64, he->stat.period);
877 break; 913 break;
878 914
879 default: 915 default:
880 break; 916 break;
881 } 917 }
882 } 918 }
883 919
884 static void 920 static void
885 hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair, 921 hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair,
886 int idx, char *buf, size_t size) 922 int idx, char *buf, size_t size)
887 { 923 {
888 double diff; 924 double diff;
889 double ratio; 925 double ratio;
890 s64 wdiff; 926 s64 wdiff;
891 927
892 switch (idx) { 928 switch (idx) {
893 case PERF_HPP_DIFF__DELTA: 929 case PERF_HPP_DIFF__DELTA:
894 if (pair->diff.computed) 930 if (pair->diff.computed)
895 diff = pair->diff.period_ratio_delta; 931 diff = pair->diff.period_ratio_delta;
896 else 932 else
897 diff = compute_delta(he, pair); 933 diff = compute_delta(he, pair);
898 934
899 if (fabs(diff) >= 0.01) 935 if (fabs(diff) >= 0.01)
900 scnprintf(buf, size, "%+4.2F%%", diff); 936 scnprintf(buf, size, "%+4.2F%%", diff);
901 break; 937 break;
902 938
903 case PERF_HPP_DIFF__RATIO: 939 case PERF_HPP_DIFF__RATIO:
904 /* No point for ratio number if we are dummy.. */ 940 /* No point for ratio number if we are dummy.. */
905 if (he->dummy) 941 if (he->dummy)
906 break; 942 break;
907 943
908 if (pair->diff.computed) 944 if (pair->diff.computed)
909 ratio = pair->diff.period_ratio; 945 ratio = pair->diff.period_ratio;
910 else 946 else
911 ratio = compute_ratio(he, pair); 947 ratio = compute_ratio(he, pair);
912 948
913 if (ratio > 0.0) 949 if (ratio > 0.0)
914 scnprintf(buf, size, "%14.6F", ratio); 950 scnprintf(buf, size, "%14.6F", ratio);
915 break; 951 break;
916 952
917 case PERF_HPP_DIFF__WEIGHTED_DIFF: 953 case PERF_HPP_DIFF__WEIGHTED_DIFF:
918 /* No point for wdiff number if we are dummy.. */ 954 /* No point for wdiff number if we are dummy.. */
919 if (he->dummy) 955 if (he->dummy)
920 break; 956 break;
921 957
922 if (pair->diff.computed) 958 if (pair->diff.computed)
923 wdiff = pair->diff.wdiff; 959 wdiff = pair->diff.wdiff;
924 else 960 else
925 wdiff = compute_wdiff(he, pair); 961 wdiff = compute_wdiff(he, pair);
926 962
927 if (wdiff != 0) 963 if (wdiff != 0)
928 scnprintf(buf, size, "%14ld", wdiff); 964 scnprintf(buf, size, "%14ld", wdiff);
929 break; 965 break;
930 966
931 case PERF_HPP_DIFF__FORMULA: 967 case PERF_HPP_DIFF__FORMULA:
932 formula_fprintf(he, pair, buf, size); 968 formula_fprintf(he, pair, buf, size);
933 break; 969 break;
934 970
935 case PERF_HPP_DIFF__PERIOD: 971 case PERF_HPP_DIFF__PERIOD:
936 scnprintf(buf, size, "%" PRIu64, pair->stat.period); 972 scnprintf(buf, size, "%" PRIu64, pair->stat.period);
937 break; 973 break;
938 974
939 default: 975 default:
940 BUG_ON(1); 976 BUG_ON(1);
941 }; 977 };
942 } 978 }
943 979
944 static void 980 static void
945 __hpp__entry_global(struct hist_entry *he, struct diff_hpp_fmt *dfmt, 981 __hpp__entry_global(struct hist_entry *he, struct diff_hpp_fmt *dfmt,
946 char *buf, size_t size) 982 char *buf, size_t size)
947 { 983 {
948 struct hist_entry *pair = get_pair_fmt(he, dfmt); 984 struct hist_entry *pair = get_pair_fmt(he, dfmt);
949 int idx = dfmt->idx; 985 int idx = dfmt->idx;
950 986
951 /* baseline is special */ 987 /* baseline is special */
952 if (idx == PERF_HPP_DIFF__BASELINE) 988 if (idx == PERF_HPP_DIFF__BASELINE)
953 hpp__entry_baseline(he, buf, size); 989 hpp__entry_baseline(he, buf, size);
954 else { 990 else {
955 if (pair) 991 if (pair)
956 hpp__entry_pair(he, pair, idx, buf, size); 992 hpp__entry_pair(he, pair, idx, buf, size);
957 else 993 else
958 hpp__entry_unpair(he, idx, buf, size); 994 hpp__entry_unpair(he, idx, buf, size);
959 } 995 }
960 } 996 }
961 997
962 static int hpp__entry_global(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp, 998 static int hpp__entry_global(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp,
963 struct hist_entry *he) 999 struct hist_entry *he)
964 { 1000 {
965 struct diff_hpp_fmt *dfmt = 1001 struct diff_hpp_fmt *dfmt =
966 container_of(_fmt, struct diff_hpp_fmt, fmt); 1002 container_of(_fmt, struct diff_hpp_fmt, fmt);
967 char buf[MAX_COL_WIDTH] = " "; 1003 char buf[MAX_COL_WIDTH] = " ";
968 1004
969 __hpp__entry_global(he, dfmt, buf, MAX_COL_WIDTH); 1005 __hpp__entry_global(he, dfmt, buf, MAX_COL_WIDTH);
970 1006
971 if (symbol_conf.field_sep) 1007 if (symbol_conf.field_sep)
972 return scnprintf(hpp->buf, hpp->size, "%s", buf); 1008 return scnprintf(hpp->buf, hpp->size, "%s", buf);
973 else 1009 else
974 return scnprintf(hpp->buf, hpp->size, "%*s", 1010 return scnprintf(hpp->buf, hpp->size, "%*s",
975 dfmt->header_width, buf); 1011 dfmt->header_width, buf);
976 } 1012 }
977 1013
978 static int hpp__header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1014 static int hpp__header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
979 struct perf_evsel *evsel __maybe_unused) 1015 struct perf_evsel *evsel __maybe_unused)
980 { 1016 {
981 struct diff_hpp_fmt *dfmt = 1017 struct diff_hpp_fmt *dfmt =
982 container_of(fmt, struct diff_hpp_fmt, fmt); 1018 container_of(fmt, struct diff_hpp_fmt, fmt);
983 1019
984 BUG_ON(!dfmt->header); 1020 BUG_ON(!dfmt->header);
985 return scnprintf(hpp->buf, hpp->size, dfmt->header); 1021 return scnprintf(hpp->buf, hpp->size, dfmt->header);
986 } 1022 }
987 1023
988 static int hpp__width(struct perf_hpp_fmt *fmt, 1024 static int hpp__width(struct perf_hpp_fmt *fmt,
989 struct perf_hpp *hpp __maybe_unused, 1025 struct perf_hpp *hpp __maybe_unused,
990 struct perf_evsel *evsel __maybe_unused) 1026 struct perf_evsel *evsel __maybe_unused)
991 { 1027 {
992 struct diff_hpp_fmt *dfmt = 1028 struct diff_hpp_fmt *dfmt =
993 container_of(fmt, struct diff_hpp_fmt, fmt); 1029 container_of(fmt, struct diff_hpp_fmt, fmt);
994 1030
995 BUG_ON(dfmt->header_width <= 0); 1031 BUG_ON(dfmt->header_width <= 0);
996 return dfmt->header_width; 1032 return dfmt->header_width;
997 } 1033 }
998 1034
999 static void init_header(struct data__file *d, struct diff_hpp_fmt *dfmt) 1035 static void init_header(struct data__file *d, struct diff_hpp_fmt *dfmt)
1000 { 1036 {
1001 #define MAX_HEADER_NAME 100 1037 #define MAX_HEADER_NAME 100
1002 char buf_indent[MAX_HEADER_NAME]; 1038 char buf_indent[MAX_HEADER_NAME];
1003 char buf[MAX_HEADER_NAME]; 1039 char buf[MAX_HEADER_NAME];
1004 const char *header = NULL; 1040 const char *header = NULL;
1005 int width = 0; 1041 int width = 0;
1006 1042
1007 BUG_ON(dfmt->idx >= PERF_HPP_DIFF__MAX_INDEX); 1043 BUG_ON(dfmt->idx >= PERF_HPP_DIFF__MAX_INDEX);
1008 header = columns[dfmt->idx].name; 1044 header = columns[dfmt->idx].name;
1009 width = columns[dfmt->idx].width; 1045 width = columns[dfmt->idx].width;
1010 1046
1011 /* Only our defined HPP fmts should appear here. */ 1047 /* Only our defined HPP fmts should appear here. */
1012 BUG_ON(!header); 1048 BUG_ON(!header);
1013 1049
1014 if (data__files_cnt > 2) 1050 if (data__files_cnt > 2)
1015 scnprintf(buf, MAX_HEADER_NAME, "%s/%d", header, d->idx); 1051 scnprintf(buf, MAX_HEADER_NAME, "%s/%d", header, d->idx);
1016 1052
1017 #define NAME (data__files_cnt > 2 ? buf : header) 1053 #define NAME (data__files_cnt > 2 ? buf : header)
1018 dfmt->header_width = width; 1054 dfmt->header_width = width;
1019 width = (int) strlen(NAME); 1055 width = (int) strlen(NAME);
1020 if (dfmt->header_width < width) 1056 if (dfmt->header_width < width)
1021 dfmt->header_width = width; 1057 dfmt->header_width = width;
1022 1058
1023 scnprintf(buf_indent, MAX_HEADER_NAME, "%*s", 1059 scnprintf(buf_indent, MAX_HEADER_NAME, "%*s",
1024 dfmt->header_width, NAME); 1060 dfmt->header_width, NAME);
1025 1061
1026 dfmt->header = strdup(buf_indent); 1062 dfmt->header = strdup(buf_indent);
1027 #undef MAX_HEADER_NAME 1063 #undef MAX_HEADER_NAME
1028 #undef NAME 1064 #undef NAME
1029 } 1065 }
1030 1066
1031 static void data__hpp_register(struct data__file *d, int idx) 1067 static void data__hpp_register(struct data__file *d, int idx)
1032 { 1068 {
1033 struct diff_hpp_fmt *dfmt = &d->fmt[idx]; 1069 struct diff_hpp_fmt *dfmt = &d->fmt[idx];
1034 struct perf_hpp_fmt *fmt = &dfmt->fmt; 1070 struct perf_hpp_fmt *fmt = &dfmt->fmt;
1035 1071
1036 dfmt->idx = idx; 1072 dfmt->idx = idx;
1037 1073
1038 fmt->header = hpp__header; 1074 fmt->header = hpp__header;
1039 fmt->width = hpp__width; 1075 fmt->width = hpp__width;
1040 fmt->entry = hpp__entry_global; 1076 fmt->entry = hpp__entry_global;
1077 fmt->cmp = hist_entry__cmp_nop;
1078 fmt->collapse = hist_entry__cmp_nop;
1041 1079
1042 /* TODO more colors */ 1080 /* TODO more colors */
1043 switch (idx) { 1081 switch (idx) {
1044 case PERF_HPP_DIFF__BASELINE: 1082 case PERF_HPP_DIFF__BASELINE:
1045 fmt->color = hpp__color_baseline; 1083 fmt->color = hpp__color_baseline;
1084 fmt->sort = hist_entry__cmp_baseline;
1046 break; 1085 break;
1047 case PERF_HPP_DIFF__DELTA: 1086 case PERF_HPP_DIFF__DELTA:
1048 fmt->color = hpp__color_delta; 1087 fmt->color = hpp__color_delta;
1088 fmt->sort = hist_entry__cmp_delta;
1049 break; 1089 break;
1050 case PERF_HPP_DIFF__RATIO: 1090 case PERF_HPP_DIFF__RATIO:
1051 fmt->color = hpp__color_ratio; 1091 fmt->color = hpp__color_ratio;
1092 fmt->sort = hist_entry__cmp_ratio;
1052 break; 1093 break;
1053 case PERF_HPP_DIFF__WEIGHTED_DIFF: 1094 case PERF_HPP_DIFF__WEIGHTED_DIFF:
1054 fmt->color = hpp__color_wdiff; 1095 fmt->color = hpp__color_wdiff;
1096 fmt->sort = hist_entry__cmp_wdiff;
1055 break; 1097 break;
1056 default: 1098 default:
1099 fmt->sort = hist_entry__cmp_nop;
1057 break; 1100 break;
1058 } 1101 }
1059 1102
1060 init_header(d, dfmt); 1103 init_header(d, dfmt);
1061 perf_hpp__column_register(fmt); 1104 perf_hpp__column_register(fmt);
1105 perf_hpp__register_sort_field(fmt);
1062 } 1106 }
1063 1107
1064 static void ui_init(void) 1108 static void ui_init(void)
1065 { 1109 {
1066 struct data__file *d; 1110 struct data__file *d;
1067 int i; 1111 int i;
1068 1112
1069 data__for_each_file(i, d) { 1113 data__for_each_file(i, d) {
1070 1114
1071 /* 1115 /*
1072 * Baseline or compute realted columns: 1116 * Baseline or compute realted columns:
1073 * 1117 *
1074 * PERF_HPP_DIFF__BASELINE 1118 * PERF_HPP_DIFF__BASELINE
1075 * PERF_HPP_DIFF__DELTA 1119 * PERF_HPP_DIFF__DELTA
1076 * PERF_HPP_DIFF__RATIO 1120 * PERF_HPP_DIFF__RATIO
1077 * PERF_HPP_DIFF__WEIGHTED_DIFF 1121 * PERF_HPP_DIFF__WEIGHTED_DIFF
1078 */ 1122 */
1079 data__hpp_register(d, i ? compute_2_hpp[compute] : 1123 data__hpp_register(d, i ? compute_2_hpp[compute] :
1080 PERF_HPP_DIFF__BASELINE); 1124 PERF_HPP_DIFF__BASELINE);
1081 1125
1082 /* 1126 /*
1083 * And the rest: 1127 * And the rest:
1084 * 1128 *
1085 * PERF_HPP_DIFF__FORMULA 1129 * PERF_HPP_DIFF__FORMULA
1086 * PERF_HPP_DIFF__PERIOD 1130 * PERF_HPP_DIFF__PERIOD
1087 * PERF_HPP_DIFF__PERIOD_BASELINE 1131 * PERF_HPP_DIFF__PERIOD_BASELINE
1088 */ 1132 */
1089 if (show_formula && i) 1133 if (show_formula && i)
1090 data__hpp_register(d, PERF_HPP_DIFF__FORMULA); 1134 data__hpp_register(d, PERF_HPP_DIFF__FORMULA);
1091 1135
1092 if (show_period) 1136 if (show_period)
1093 data__hpp_register(d, i ? PERF_HPP_DIFF__PERIOD : 1137 data__hpp_register(d, i ? PERF_HPP_DIFF__PERIOD :
1094 PERF_HPP_DIFF__PERIOD_BASELINE); 1138 PERF_HPP_DIFF__PERIOD_BASELINE);
1095 } 1139 }
1096 } 1140 }
1097 1141
1098 static int data_init(int argc, const char **argv) 1142 static int data_init(int argc, const char **argv)
1099 { 1143 {
1100 struct data__file *d; 1144 struct data__file *d;
1101 static const char *defaults[] = { 1145 static const char *defaults[] = {
1102 "perf.data.old", 1146 "perf.data.old",
1103 "perf.data", 1147 "perf.data",
1104 }; 1148 };
1105 bool use_default = true; 1149 bool use_default = true;
1106 int i; 1150 int i;
1107 1151
1108 data__files_cnt = 2; 1152 data__files_cnt = 2;
1109 1153
1110 if (argc) { 1154 if (argc) {
1111 if (argc == 1) 1155 if (argc == 1)
1112 defaults[1] = argv[0]; 1156 defaults[1] = argv[0];
1113 else { 1157 else {
1114 data__files_cnt = argc; 1158 data__files_cnt = argc;
1115 use_default = false; 1159 use_default = false;
1116 } 1160 }
1117 } else if (perf_guest) { 1161 } else if (perf_guest) {
1118 defaults[0] = "perf.data.host"; 1162 defaults[0] = "perf.data.host";
1119 defaults[1] = "perf.data.guest"; 1163 defaults[1] = "perf.data.guest";
1120 } 1164 }
1121 1165
1122 if (sort_compute >= (unsigned int) data__files_cnt) { 1166 if (sort_compute >= (unsigned int) data__files_cnt) {
1123 pr_err("Order option out of limit.\n"); 1167 pr_err("Order option out of limit.\n");
1124 return -EINVAL; 1168 return -EINVAL;
1125 } 1169 }
1126 1170
1127 data__files = zalloc(sizeof(*data__files) * data__files_cnt); 1171 data__files = zalloc(sizeof(*data__files) * data__files_cnt);
1128 if (!data__files) 1172 if (!data__files)
1129 return -ENOMEM; 1173 return -ENOMEM;
1130 1174
1131 data__for_each_file(i, d) { 1175 data__for_each_file(i, d) {
1132 struct perf_data_file *file = &d->file; 1176 struct perf_data_file *file = &d->file;
1133 1177
1134 file->path = use_default ? defaults[i] : argv[i]; 1178 file->path = use_default ? defaults[i] : argv[i];
1135 file->mode = PERF_DATA_MODE_READ, 1179 file->mode = PERF_DATA_MODE_READ,
1136 file->force = force, 1180 file->force = force,
1137 1181
1138 d->idx = i; 1182 d->idx = i;
1139 } 1183 }
1140 1184
1141 return 0; 1185 return 0;
1142 } 1186 }
1143 1187
1144 int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) 1188 int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
1145 { 1189 {
1146 int ret = hists__init(); 1190 int ret = hists__init();
1147 1191
1148 if (ret < 0) 1192 if (ret < 0)
1149 return ret; 1193 return ret;
1150 1194
1151 perf_config(perf_default_config, NULL); 1195 perf_config(perf_default_config, NULL);
1152 1196
1153 argc = parse_options(argc, argv, options, diff_usage, 0); 1197 argc = parse_options(argc, argv, options, diff_usage, 0);
1154 1198
1155 if (symbol__init(NULL) < 0) 1199 if (symbol__init(NULL) < 0)
1156 return -1; 1200 return -1;
1157 1201
1158 if (data_init(argc, argv) < 0) 1202 if (data_init(argc, argv) < 0)
1159 return -1; 1203 return -1;
1160 1204
1161 ui_init(); 1205 ui_init();
1162 1206
1163 sort__mode = SORT_MODE__DIFF; 1207 sort__mode = SORT_MODE__DIFF;
1164 1208
1165 if (setup_sorting() < 0) 1209 if (setup_sorting() < 0)
1166 usage_with_options(diff_usage, options); 1210 usage_with_options(diff_usage, options);
1167 1211
1168 setup_pager(); 1212 setup_pager();
1169 1213
1170 sort__setup_elide(NULL); 1214 sort__setup_elide(NULL);
1171 1215
1172 return __cmd_diff(); 1216 return __cmd_diff();
1173 } 1217 }
1174 1218
tools/perf/builtin-list.c
1 /* 1 /*
2 * builtin-list.c 2 * builtin-list.c
3 * 3 *
4 * Builtin list command: list all event types 4 * Builtin list command: list all event types
5 * 5 *
6 * Copyright (C) 2009, Thomas Gleixner <tglx@linutronix.de> 6 * Copyright (C) 2009, Thomas Gleixner <tglx@linutronix.de>
7 * Copyright (C) 2008-2009, Red Hat Inc, Ingo Molnar <mingo@redhat.com> 7 * Copyright (C) 2008-2009, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
8 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 8 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
9 */ 9 */
10 #include "builtin.h" 10 #include "builtin.h"
11 11
12 #include "perf.h" 12 #include "perf.h"
13 13
14 #include "util/parse-events.h" 14 #include "util/parse-events.h"
15 #include "util/cache.h" 15 #include "util/cache.h"
16 #include "util/pmu.h" 16 #include "util/pmu.h"
17 #include "util/parse-options.h" 17 #include "util/parse-options.h"
18 18
19 int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) 19 int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
20 { 20 {
21 int i; 21 int i;
22 const struct option list_options[] = { 22 bool raw_dump = false;
23 struct option list_options[] = {
24 OPT_BOOLEAN(0, "raw-dump", &raw_dump, "Dump raw events"),
23 OPT_END() 25 OPT_END()
24 }; 26 };
25 const char * const list_usage[] = { 27 const char * const list_usage[] = {
26 "perf list [hw|sw|cache|tracepoint|pmu|event_glob]", 28 "perf list [hw|sw|cache|tracepoint|pmu|event_glob]",
27 NULL 29 NULL
28 }; 30 };
29 31
32 set_option_flag(list_options, 0, "raw-dump", PARSE_OPT_HIDDEN);
33
30 argc = parse_options(argc, argv, list_options, list_usage, 34 argc = parse_options(argc, argv, list_options, list_usage,
31 PARSE_OPT_STOP_AT_NON_OPTION); 35 PARSE_OPT_STOP_AT_NON_OPTION);
32 36
33 setup_pager(); 37 setup_pager();
34 38
39 if (raw_dump) {
40 print_events(NULL, true);
41 return 0;
42 }
43
35 if (argc == 0) { 44 if (argc == 0) {
36 print_events(NULL, false); 45 print_events(NULL, false);
37 return 0; 46 return 0;
38 } 47 }
39 48
40 for (i = 0; i < argc; ++i) { 49 for (i = 0; i < argc; ++i) {
41 if (i) 50 if (i)
42 putchar('\n'); 51 putchar('\n');
43 if (strncmp(argv[i], "tracepoint", 10) == 0) 52 if (strncmp(argv[i], "tracepoint", 10) == 0)
44 print_tracepoint_events(NULL, NULL, false); 53 print_tracepoint_events(NULL, NULL, false);
45 else if (strcmp(argv[i], "hw") == 0 || 54 else if (strcmp(argv[i], "hw") == 0 ||
46 strcmp(argv[i], "hardware") == 0) 55 strcmp(argv[i], "hardware") == 0)
47 print_events_type(PERF_TYPE_HARDWARE); 56 print_events_type(PERF_TYPE_HARDWARE);
48 else if (strcmp(argv[i], "sw") == 0 || 57 else if (strcmp(argv[i], "sw") == 0 ||
49 strcmp(argv[i], "software") == 0) 58 strcmp(argv[i], "software") == 0)
50 print_events_type(PERF_TYPE_SOFTWARE); 59 print_events_type(PERF_TYPE_SOFTWARE);
51 else if (strcmp(argv[i], "cache") == 0 || 60 else if (strcmp(argv[i], "cache") == 0 ||
52 strcmp(argv[i], "hwcache") == 0) 61 strcmp(argv[i], "hwcache") == 0)
53 print_hwcache_events(NULL, false); 62 print_hwcache_events(NULL, false);
54 else if (strcmp(argv[i], "pmu") == 0) 63 else if (strcmp(argv[i], "pmu") == 0)
55 print_pmu_events(NULL, false); 64 print_pmu_events(NULL, false);
56 else if (strcmp(argv[i], "--raw-dump") == 0)
57 print_events(NULL, true);
58 else { 65 else {
59 char *sep = strchr(argv[i], ':'), *s; 66 char *sep = strchr(argv[i], ':'), *s;
60 int sep_idx; 67 int sep_idx;
61 68
62 if (sep == NULL) { 69 if (sep == NULL) {
63 print_events(argv[i], false); 70 print_events(argv[i], false);
64 continue; 71 continue;
65 } 72 }
66 sep_idx = sep - argv[i]; 73 sep_idx = sep - argv[i];
67 s = strdup(argv[i]); 74 s = strdup(argv[i]);
68 if (s == NULL) 75 if (s == NULL)
69 return -1; 76 return -1;
70 77
71 s[sep_idx] = '\0'; 78 s[sep_idx] = '\0';
72 print_tracepoint_events(s, s + sep_idx + 1, false); 79 print_tracepoint_events(s, s + sep_idx + 1, false);
73 free(s); 80 free(s);
74 } 81 }
75 } 82 }
76 return 0; 83 return 0;
tools/perf/util/probe-event.c
1 /* 1 /*
2 * probe-event.c : perf-probe definition to probe_events format converter 2 * probe-event.c : perf-probe definition to probe_events format converter
3 * 3 *
4 * Written by Masami Hiramatsu <mhiramat@redhat.com> 4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or 8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version. 9 * (at your option) any later version.
10 * 10 *
11 * This program is distributed in the hope that it will be useful, 11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU General Public License 16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software 17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 * 19 *
20 */ 20 */
21 21
22 #include <sys/utsname.h> 22 #include <sys/utsname.h>
23 #include <sys/types.h> 23 #include <sys/types.h>
24 #include <sys/stat.h> 24 #include <sys/stat.h>
25 #include <fcntl.h> 25 #include <fcntl.h>
26 #include <errno.h> 26 #include <errno.h>
27 #include <stdio.h> 27 #include <stdio.h>
28 #include <unistd.h> 28 #include <unistd.h>
29 #include <stdlib.h> 29 #include <stdlib.h>
30 #include <string.h> 30 #include <string.h>
31 #include <stdarg.h> 31 #include <stdarg.h>
32 #include <limits.h> 32 #include <limits.h>
33 #include <elf.h> 33 #include <elf.h>
34 34
35 #include "util.h" 35 #include "util.h"
36 #include "event.h" 36 #include "event.h"
37 #include "strlist.h" 37 #include "strlist.h"
38 #include "debug.h" 38 #include "debug.h"
39 #include "cache.h" 39 #include "cache.h"
40 #include "color.h" 40 #include "color.h"
41 #include "symbol.h" 41 #include "symbol.h"
42 #include "thread.h" 42 #include "thread.h"
43 #include <api/fs/debugfs.h> 43 #include <api/fs/debugfs.h>
44 #include "trace-event.h" /* For __maybe_unused */ 44 #include "trace-event.h" /* For __maybe_unused */
45 #include "probe-event.h" 45 #include "probe-event.h"
46 #include "probe-finder.h" 46 #include "probe-finder.h"
47 #include "session.h" 47 #include "session.h"
48 48
49 #define MAX_CMDLEN 256 49 #define MAX_CMDLEN 256
50 #define PERFPROBE_GROUP "probe" 50 #define PERFPROBE_GROUP "probe"
51 51
52 bool probe_event_dry_run; /* Dry run flag */ 52 bool probe_event_dry_run; /* Dry run flag */
53 53
54 #define semantic_error(msg ...) pr_err("Semantic error :" msg) 54 #define semantic_error(msg ...) pr_err("Semantic error :" msg)
55 55
56 /* If there is no space to write, returns -E2BIG. */ 56 /* If there is no space to write, returns -E2BIG. */
57 static int e_snprintf(char *str, size_t size, const char *format, ...) 57 static int e_snprintf(char *str, size_t size, const char *format, ...)
58 __attribute__((format(printf, 3, 4))); 58 __attribute__((format(printf, 3, 4)));
59 59
60 static int e_snprintf(char *str, size_t size, const char *format, ...) 60 static int e_snprintf(char *str, size_t size, const char *format, ...)
61 { 61 {
62 int ret; 62 int ret;
63 va_list ap; 63 va_list ap;
64 va_start(ap, format); 64 va_start(ap, format);
65 ret = vsnprintf(str, size, format, ap); 65 ret = vsnprintf(str, size, format, ap);
66 va_end(ap); 66 va_end(ap);
67 if (ret >= (int)size) 67 if (ret >= (int)size)
68 ret = -E2BIG; 68 ret = -E2BIG;
69 return ret; 69 return ret;
70 } 70 }
71 71
72 static char *synthesize_perf_probe_point(struct perf_probe_point *pp); 72 static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
73 static void clear_probe_trace_event(struct probe_trace_event *tev); 73 static void clear_probe_trace_event(struct probe_trace_event *tev);
74 static struct machine *host_machine; 74 static struct machine *host_machine;
75 75
76 /* Initialize symbol maps and path of vmlinux/modules */ 76 /* Initialize symbol maps and path of vmlinux/modules */
77 static int init_symbol_maps(bool user_only) 77 static int init_symbol_maps(bool user_only)
78 { 78 {
79 int ret; 79 int ret;
80 80
81 symbol_conf.sort_by_name = true; 81 symbol_conf.sort_by_name = true;
82 ret = symbol__init(NULL); 82 ret = symbol__init(NULL);
83 if (ret < 0) { 83 if (ret < 0) {
84 pr_debug("Failed to init symbol map.\n"); 84 pr_debug("Failed to init symbol map.\n");
85 goto out; 85 goto out;
86 } 86 }
87 87
88 if (host_machine || user_only) /* already initialized */ 88 if (host_machine || user_only) /* already initialized */
89 return 0; 89 return 0;
90 90
91 if (symbol_conf.vmlinux_name) 91 if (symbol_conf.vmlinux_name)
92 pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name); 92 pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
93 93
94 host_machine = machine__new_host(); 94 host_machine = machine__new_host();
95 if (!host_machine) { 95 if (!host_machine) {
96 pr_debug("machine__new_host() failed.\n"); 96 pr_debug("machine__new_host() failed.\n");
97 symbol__exit(); 97 symbol__exit();
98 ret = -1; 98 ret = -1;
99 } 99 }
100 out: 100 out:
101 if (ret < 0) 101 if (ret < 0)
102 pr_warning("Failed to init vmlinux path.\n"); 102 pr_warning("Failed to init vmlinux path.\n");
103 return ret; 103 return ret;
104 } 104 }
105 105
106 static void exit_symbol_maps(void) 106 static void exit_symbol_maps(void)
107 { 107 {
108 if (host_machine) { 108 if (host_machine) {
109 machine__delete(host_machine); 109 machine__delete(host_machine);
110 host_machine = NULL; 110 host_machine = NULL;
111 } 111 }
112 symbol__exit(); 112 symbol__exit();
113 } 113 }
114 114
115 static struct symbol *__find_kernel_function_by_name(const char *name, 115 static struct symbol *__find_kernel_function_by_name(const char *name,
116 struct map **mapp) 116 struct map **mapp)
117 { 117 {
118 return machine__find_kernel_function_by_name(host_machine, name, mapp, 118 return machine__find_kernel_function_by_name(host_machine, name, mapp,
119 NULL); 119 NULL);
120 } 120 }
121 121
122 static struct symbol *__find_kernel_function(u64 addr, struct map **mapp) 122 static struct symbol *__find_kernel_function(u64 addr, struct map **mapp)
123 { 123 {
124 return machine__find_kernel_function(host_machine, addr, mapp, NULL); 124 return machine__find_kernel_function(host_machine, addr, mapp, NULL);
125 } 125 }
126 126
127 static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void) 127 static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
128 { 128 {
129 /* kmap->ref_reloc_sym should be set if host_machine is initialized */ 129 /* kmap->ref_reloc_sym should be set if host_machine is initialized */
130 struct kmap *kmap; 130 struct kmap *kmap;
131 131
132 if (map__load(host_machine->vmlinux_maps[MAP__FUNCTION], NULL) < 0) 132 if (map__load(host_machine->vmlinux_maps[MAP__FUNCTION], NULL) < 0)
133 return NULL; 133 return NULL;
134 134
135 kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]); 135 kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]);
136 return kmap->ref_reloc_sym; 136 return kmap->ref_reloc_sym;
137 } 137 }
138 138
139 static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc) 139 static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc)
140 { 140 {
141 struct ref_reloc_sym *reloc_sym; 141 struct ref_reloc_sym *reloc_sym;
142 struct symbol *sym; 142 struct symbol *sym;
143 struct map *map; 143 struct map *map;
144 144
145 /* ref_reloc_sym is just a label. Need a special fix*/ 145 /* ref_reloc_sym is just a label. Need a special fix*/
146 reloc_sym = kernel_get_ref_reloc_sym(); 146 reloc_sym = kernel_get_ref_reloc_sym();
147 if (reloc_sym && strcmp(name, reloc_sym->name) == 0) 147 if (reloc_sym && strcmp(name, reloc_sym->name) == 0)
148 return (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr; 148 return (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr;
149 else { 149 else {
150 sym = __find_kernel_function_by_name(name, &map); 150 sym = __find_kernel_function_by_name(name, &map);
151 if (sym) 151 if (sym)
152 return map->unmap_ip(map, sym->start) - 152 return map->unmap_ip(map, sym->start) -
153 (reloc) ? 0 : map->reloc; 153 (reloc) ? 0 : map->reloc;
154 } 154 }
155 return 0; 155 return 0;
156 } 156 }
157 157
158 static struct map *kernel_get_module_map(const char *module) 158 static struct map *kernel_get_module_map(const char *module)
159 { 159 {
160 struct rb_node *nd; 160 struct rb_node *nd;
161 struct map_groups *grp = &host_machine->kmaps; 161 struct map_groups *grp = &host_machine->kmaps;
162 162
163 /* A file path -- this is an offline module */ 163 /* A file path -- this is an offline module */
164 if (module && strchr(module, '/')) 164 if (module && strchr(module, '/'))
165 return machine__new_module(host_machine, 0, module); 165 return machine__new_module(host_machine, 0, module);
166 166
167 if (!module) 167 if (!module)
168 module = "kernel"; 168 module = "kernel";
169 169
170 for (nd = rb_first(&grp->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) { 170 for (nd = rb_first(&grp->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) {
171 struct map *pos = rb_entry(nd, struct map, rb_node); 171 struct map *pos = rb_entry(nd, struct map, rb_node);
172 if (strncmp(pos->dso->short_name + 1, module, 172 if (strncmp(pos->dso->short_name + 1, module,
173 pos->dso->short_name_len - 2) == 0) { 173 pos->dso->short_name_len - 2) == 0) {
174 return pos; 174 return pos;
175 } 175 }
176 } 176 }
177 return NULL; 177 return NULL;
178 } 178 }
179 179
180 static struct dso *kernel_get_module_dso(const char *module) 180 static struct dso *kernel_get_module_dso(const char *module)
181 { 181 {
182 struct dso *dso; 182 struct dso *dso;
183 struct map *map; 183 struct map *map;
184 const char *vmlinux_name; 184 const char *vmlinux_name;
185 185
186 if (module) { 186 if (module) {
187 list_for_each_entry(dso, &host_machine->kernel_dsos.head, 187 list_for_each_entry(dso, &host_machine->kernel_dsos.head,
188 node) { 188 node) {
189 if (strncmp(dso->short_name + 1, module, 189 if (strncmp(dso->short_name + 1, module,
190 dso->short_name_len - 2) == 0) 190 dso->short_name_len - 2) == 0)
191 goto found; 191 goto found;
192 } 192 }
193 pr_debug("Failed to find module %s.\n", module); 193 pr_debug("Failed to find module %s.\n", module);
194 return NULL; 194 return NULL;
195 } 195 }
196 196
197 map = host_machine->vmlinux_maps[MAP__FUNCTION]; 197 map = host_machine->vmlinux_maps[MAP__FUNCTION];
198 dso = map->dso; 198 dso = map->dso;
199 199
200 vmlinux_name = symbol_conf.vmlinux_name; 200 vmlinux_name = symbol_conf.vmlinux_name;
201 if (vmlinux_name) { 201 if (vmlinux_name) {
202 if (dso__load_vmlinux(dso, map, vmlinux_name, false, NULL) <= 0) 202 if (dso__load_vmlinux(dso, map, vmlinux_name, false, NULL) <= 0)
203 return NULL; 203 return NULL;
204 } else { 204 } else {
205 if (dso__load_vmlinux_path(dso, map, NULL) <= 0) { 205 if (dso__load_vmlinux_path(dso, map, NULL) <= 0) {
206 pr_debug("Failed to load kernel map.\n"); 206 pr_debug("Failed to load kernel map.\n");
207 return NULL; 207 return NULL;
208 } 208 }
209 } 209 }
210 found: 210 found:
211 return dso; 211 return dso;
212 } 212 }
213 213
214 const char *kernel_get_module_path(const char *module) 214 const char *kernel_get_module_path(const char *module)
215 { 215 {
216 struct dso *dso = kernel_get_module_dso(module); 216 struct dso *dso = kernel_get_module_dso(module);
217 return (dso) ? dso->long_name : NULL; 217 return (dso) ? dso->long_name : NULL;
218 } 218 }
219 219
220 static int convert_exec_to_group(const char *exec, char **result) 220 static int convert_exec_to_group(const char *exec, char **result)
221 { 221 {
222 char *ptr1, *ptr2, *exec_copy; 222 char *ptr1, *ptr2, *exec_copy;
223 char buf[64]; 223 char buf[64];
224 int ret; 224 int ret;
225 225
226 exec_copy = strdup(exec); 226 exec_copy = strdup(exec);
227 if (!exec_copy) 227 if (!exec_copy)
228 return -ENOMEM; 228 return -ENOMEM;
229 229
230 ptr1 = basename(exec_copy); 230 ptr1 = basename(exec_copy);
231 if (!ptr1) { 231 if (!ptr1) {
232 ret = -EINVAL; 232 ret = -EINVAL;
233 goto out; 233 goto out;
234 } 234 }
235 235
236 ptr2 = strpbrk(ptr1, "-._"); 236 ptr2 = strpbrk(ptr1, "-._");
237 if (ptr2) 237 if (ptr2)
238 *ptr2 = '\0'; 238 *ptr2 = '\0';
239 ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1); 239 ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1);
240 if (ret < 0) 240 if (ret < 0)
241 goto out; 241 goto out;
242 242
243 *result = strdup(buf); 243 *result = strdup(buf);
244 ret = *result ? 0 : -ENOMEM; 244 ret = *result ? 0 : -ENOMEM;
245 245
246 out: 246 out:
247 free(exec_copy); 247 free(exec_copy);
248 return ret; 248 return ret;
249 } 249 }
250 250
251 static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs) 251 static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
252 { 252 {
253 int i; 253 int i;
254 254
255 for (i = 0; i < ntevs; i++) 255 for (i = 0; i < ntevs; i++)
256 clear_probe_trace_event(tevs + i); 256 clear_probe_trace_event(tevs + i);
257 } 257 }
258 258
259 #ifdef HAVE_DWARF_SUPPORT 259 #ifdef HAVE_DWARF_SUPPORT
260 260
261 /* Open new debuginfo of given module */ 261 /* Open new debuginfo of given module */
262 static struct debuginfo *open_debuginfo(const char *module, bool silent) 262 static struct debuginfo *open_debuginfo(const char *module, bool silent)
263 { 263 {
264 const char *path = module; 264 const char *path = module;
265 struct debuginfo *ret; 265 struct debuginfo *ret;
266 266
267 if (!module || !strchr(module, '/')) { 267 if (!module || !strchr(module, '/')) {
268 path = kernel_get_module_path(module); 268 path = kernel_get_module_path(module);
269 if (!path) { 269 if (!path) {
270 if (!silent) 270 if (!silent)
271 pr_err("Failed to find path of %s module.\n", 271 pr_err("Failed to find path of %s module.\n",
272 module ?: "kernel"); 272 module ?: "kernel");
273 return NULL; 273 return NULL;
274 } 274 }
275 } 275 }
276 ret = debuginfo__new(path); 276 ret = debuginfo__new(path);
277 if (!ret && !silent) { 277 if (!ret && !silent) {
278 pr_warning("The %s file has no debug information.\n", path); 278 pr_warning("The %s file has no debug information.\n", path);
279 if (!module || !strtailcmp(path, ".ko")) 279 if (!module || !strtailcmp(path, ".ko"))
280 pr_warning("Rebuild with CONFIG_DEBUG_INFO=y, "); 280 pr_warning("Rebuild with CONFIG_DEBUG_INFO=y, ");
281 else 281 else
282 pr_warning("Rebuild with -g, "); 282 pr_warning("Rebuild with -g, ");
283 pr_warning("or install an appropriate debuginfo package.\n"); 283 pr_warning("or install an appropriate debuginfo package.\n");
284 } 284 }
285 return ret; 285 return ret;
286 } 286 }
287 287
288 288
289 static int get_text_start_address(const char *exec, unsigned long *address) 289 static int get_text_start_address(const char *exec, unsigned long *address)
290 { 290 {
291 Elf *elf; 291 Elf *elf;
292 GElf_Ehdr ehdr; 292 GElf_Ehdr ehdr;
293 GElf_Shdr shdr; 293 GElf_Shdr shdr;
294 int fd, ret = -ENOENT; 294 int fd, ret = -ENOENT;
295 295
296 fd = open(exec, O_RDONLY); 296 fd = open(exec, O_RDONLY);
297 if (fd < 0) 297 if (fd < 0)
298 return -errno; 298 return -errno;
299 299
300 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 300 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
301 if (elf == NULL) 301 if (elf == NULL)
302 return -EINVAL; 302 return -EINVAL;
303 303
304 if (gelf_getehdr(elf, &ehdr) == NULL) 304 if (gelf_getehdr(elf, &ehdr) == NULL)
305 goto out; 305 goto out;
306 306
307 if (!elf_section_by_name(elf, &ehdr, &shdr, ".text", NULL)) 307 if (!elf_section_by_name(elf, &ehdr, &shdr, ".text", NULL))
308 goto out; 308 goto out;
309 309
310 *address = shdr.sh_addr - shdr.sh_offset; 310 *address = shdr.sh_addr - shdr.sh_offset;
311 ret = 0; 311 ret = 0;
312 out: 312 out:
313 elf_end(elf); 313 elf_end(elf);
314 return ret; 314 return ret;
315 } 315 }
316 316
317 /* 317 /*
318 * Convert trace point to probe point with debuginfo 318 * Convert trace point to probe point with debuginfo
319 */ 319 */
320 static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp, 320 static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
321 struct perf_probe_point *pp, 321 struct perf_probe_point *pp,
322 bool is_kprobe) 322 bool is_kprobe)
323 { 323 {
324 struct debuginfo *dinfo = NULL; 324 struct debuginfo *dinfo = NULL;
325 unsigned long stext = 0; 325 unsigned long stext = 0;
326 u64 addr = tp->address; 326 u64 addr = tp->address;
327 int ret = -ENOENT; 327 int ret = -ENOENT;
328 328
329 /* convert the address to dwarf address */ 329 /* convert the address to dwarf address */
330 if (!is_kprobe) { 330 if (!is_kprobe) {
331 if (!addr) { 331 if (!addr) {
332 ret = -EINVAL; 332 ret = -EINVAL;
333 goto error; 333 goto error;
334 } 334 }
335 ret = get_text_start_address(tp->module, &stext); 335 ret = get_text_start_address(tp->module, &stext);
336 if (ret < 0) 336 if (ret < 0)
337 goto error; 337 goto error;
338 addr += stext; 338 addr += stext;
339 } else { 339 } else {
340 addr = kernel_get_symbol_address_by_name(tp->symbol, false); 340 addr = kernel_get_symbol_address_by_name(tp->symbol, false);
341 if (addr == 0) 341 if (addr == 0)
342 goto error; 342 goto error;
343 addr += tp->offset; 343 addr += tp->offset;
344 } 344 }
345 345
346 pr_debug("try to find information at %" PRIx64 " in %s\n", addr, 346 pr_debug("try to find information at %" PRIx64 " in %s\n", addr,
347 tp->module ? : "kernel"); 347 tp->module ? : "kernel");
348 348
349 dinfo = open_debuginfo(tp->module, verbose == 0); 349 dinfo = open_debuginfo(tp->module, verbose == 0);
350 if (dinfo) { 350 if (dinfo) {
351 ret = debuginfo__find_probe_point(dinfo, 351 ret = debuginfo__find_probe_point(dinfo,
352 (unsigned long)addr, pp); 352 (unsigned long)addr, pp);
353 debuginfo__delete(dinfo); 353 debuginfo__delete(dinfo);
354 } else 354 } else
355 ret = -ENOENT; 355 ret = -ENOENT;
356 356
357 if (ret > 0) { 357 if (ret > 0) {
358 pp->retprobe = tp->retprobe; 358 pp->retprobe = tp->retprobe;
359 return 0; 359 return 0;
360 } 360 }
361 error: 361 error:
362 pr_debug("Failed to find corresponding probes from debuginfo.\n"); 362 pr_debug("Failed to find corresponding probes from debuginfo.\n");
363 return ret ? : -ENOENT; 363 return ret ? : -ENOENT;
364 } 364 }
365 365
366 static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, 366 static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
367 int ntevs, const char *exec) 367 int ntevs, const char *exec)
368 { 368 {
369 int i, ret = 0; 369 int i, ret = 0;
370 unsigned long stext = 0; 370 unsigned long stext = 0;
371 371
372 if (!exec) 372 if (!exec)
373 return 0; 373 return 0;
374 374
375 ret = get_text_start_address(exec, &stext); 375 ret = get_text_start_address(exec, &stext);
376 if (ret < 0) 376 if (ret < 0)
377 return ret; 377 return ret;
378 378
379 for (i = 0; i < ntevs && ret >= 0; i++) { 379 for (i = 0; i < ntevs && ret >= 0; i++) {
380 /* point.address is the addres of point.symbol + point.offset */ 380 /* point.address is the addres of point.symbol + point.offset */
381 tevs[i].point.address -= stext; 381 tevs[i].point.address -= stext;
382 tevs[i].point.module = strdup(exec); 382 tevs[i].point.module = strdup(exec);
383 if (!tevs[i].point.module) { 383 if (!tevs[i].point.module) {
384 ret = -ENOMEM; 384 ret = -ENOMEM;
385 break; 385 break;
386 } 386 }
387 tevs[i].uprobes = true; 387 tevs[i].uprobes = true;
388 } 388 }
389 389
390 return ret; 390 return ret;
391 } 391 }
392 392
393 static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, 393 static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
394 int ntevs, const char *module) 394 int ntevs, const char *module)
395 { 395 {
396 int i, ret = 0; 396 int i, ret = 0;
397 char *tmp; 397 char *tmp;
398 398
399 if (!module) 399 if (!module)
400 return 0; 400 return 0;
401 401
402 tmp = strrchr(module, '/'); 402 tmp = strrchr(module, '/');
403 if (tmp) { 403 if (tmp) {
404 /* This is a module path -- get the module name */ 404 /* This is a module path -- get the module name */
405 module = strdup(tmp + 1); 405 module = strdup(tmp + 1);
406 if (!module) 406 if (!module)
407 return -ENOMEM; 407 return -ENOMEM;
408 tmp = strchr(module, '.'); 408 tmp = strchr(module, '.');
409 if (tmp) 409 if (tmp)
410 *tmp = '\0'; 410 *tmp = '\0';
411 tmp = (char *)module; /* For free() */ 411 tmp = (char *)module; /* For free() */
412 } 412 }
413 413
414 for (i = 0; i < ntevs; i++) { 414 for (i = 0; i < ntevs; i++) {
415 tevs[i].point.module = strdup(module); 415 tevs[i].point.module = strdup(module);
416 if (!tevs[i].point.module) { 416 if (!tevs[i].point.module) {
417 ret = -ENOMEM; 417 ret = -ENOMEM;
418 break; 418 break;
419 } 419 }
420 } 420 }
421 421
422 free(tmp); 422 free(tmp);
423 return ret; 423 return ret;
424 } 424 }
425 425
426 /* Post processing the probe events */ 426 /* Post processing the probe events */
427 static int post_process_probe_trace_events(struct probe_trace_event *tevs, 427 static int post_process_probe_trace_events(struct probe_trace_event *tevs,
428 int ntevs, const char *module, 428 int ntevs, const char *module,
429 bool uprobe) 429 bool uprobe)
430 { 430 {
431 struct ref_reloc_sym *reloc_sym; 431 struct ref_reloc_sym *reloc_sym;
432 char *tmp; 432 char *tmp;
433 int i; 433 int i;
434 434
435 if (uprobe) 435 if (uprobe)
436 return add_exec_to_probe_trace_events(tevs, ntevs, module); 436 return add_exec_to_probe_trace_events(tevs, ntevs, module);
437 437
438 /* Note that currently ref_reloc_sym based probe is not for drivers */ 438 /* Note that currently ref_reloc_sym based probe is not for drivers */
439 if (module) 439 if (module)
440 return add_module_to_probe_trace_events(tevs, ntevs, module); 440 return add_module_to_probe_trace_events(tevs, ntevs, module);
441 441
442 reloc_sym = kernel_get_ref_reloc_sym(); 442 reloc_sym = kernel_get_ref_reloc_sym();
443 if (!reloc_sym) { 443 if (!reloc_sym) {
444 pr_warning("Relocated base symbol is not found!\n"); 444 pr_warning("Relocated base symbol is not found!\n");
445 return -EINVAL; 445 return -EINVAL;
446 } 446 }
447 447
448 for (i = 0; i < ntevs; i++) { 448 for (i = 0; i < ntevs; i++) {
449 if (tevs[i].point.address) { 449 if (tevs[i].point.address) {
450 tmp = strdup(reloc_sym->name); 450 tmp = strdup(reloc_sym->name);
451 if (!tmp) 451 if (!tmp)
452 return -ENOMEM; 452 return -ENOMEM;
453 free(tevs[i].point.symbol); 453 free(tevs[i].point.symbol);
454 tevs[i].point.symbol = tmp; 454 tevs[i].point.symbol = tmp;
455 tevs[i].point.offset = tevs[i].point.address - 455 tevs[i].point.offset = tevs[i].point.address -
456 reloc_sym->unrelocated_addr; 456 reloc_sym->unrelocated_addr;
457 } 457 }
458 } 458 }
459 return 0; 459 return 0;
460 } 460 }
461 461
462 /* Try to find perf_probe_event with debuginfo */ 462 /* Try to find perf_probe_event with debuginfo */
463 static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 463 static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
464 struct probe_trace_event **tevs, 464 struct probe_trace_event **tevs,
465 int max_tevs, const char *target) 465 int max_tevs, const char *target)
466 { 466 {
467 bool need_dwarf = perf_probe_event_need_dwarf(pev); 467 bool need_dwarf = perf_probe_event_need_dwarf(pev);
468 struct debuginfo *dinfo; 468 struct debuginfo *dinfo;
469 int ntevs, ret = 0; 469 int ntevs, ret = 0;
470 470
471 dinfo = open_debuginfo(target, !need_dwarf); 471 dinfo = open_debuginfo(target, !need_dwarf);
472 472
473 if (!dinfo) { 473 if (!dinfo) {
474 if (need_dwarf) 474 if (need_dwarf)
475 return -ENOENT; 475 return -ENOENT;
476 pr_debug("Could not open debuginfo. Try to use symbols.\n"); 476 pr_debug("Could not open debuginfo. Try to use symbols.\n");
477 return 0; 477 return 0;
478 } 478 }
479 479
480 pr_debug("Try to find probe point from debuginfo.\n"); 480 pr_debug("Try to find probe point from debuginfo.\n");
481 /* Searching trace events corresponding to a probe event */ 481 /* Searching trace events corresponding to a probe event */
482 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs); 482 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
483 483
484 debuginfo__delete(dinfo); 484 debuginfo__delete(dinfo);
485 485
486 if (ntevs > 0) { /* Succeeded to find trace events */ 486 if (ntevs > 0) { /* Succeeded to find trace events */
487 pr_debug("Found %d probe_trace_events.\n", ntevs); 487 pr_debug("Found %d probe_trace_events.\n", ntevs);
488 ret = post_process_probe_trace_events(*tevs, ntevs, 488 ret = post_process_probe_trace_events(*tevs, ntevs,
489 target, pev->uprobes); 489 target, pev->uprobes);
490 if (ret < 0) { 490 if (ret < 0) {
491 clear_probe_trace_events(*tevs, ntevs); 491 clear_probe_trace_events(*tevs, ntevs);
492 zfree(tevs); 492 zfree(tevs);
493 } 493 }
494 return ret < 0 ? ret : ntevs; 494 return ret < 0 ? ret : ntevs;
495 } 495 }
496 496
497 if (ntevs == 0) { /* No error but failed to find probe point. */ 497 if (ntevs == 0) { /* No error but failed to find probe point. */
498 pr_warning("Probe point '%s' not found.\n", 498 pr_warning("Probe point '%s' not found in debuginfo.\n",
499 synthesize_perf_probe_point(&pev->point)); 499 synthesize_perf_probe_point(&pev->point));
500 return -ENOENT; 500 if (need_dwarf)
501 return -ENOENT;
502 return 0;
501 } 503 }
502 /* Error path : ntevs < 0 */ 504 /* Error path : ntevs < 0 */
503 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); 505 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
504 if (ntevs == -EBADF) { 506 if (ntevs == -EBADF) {
505 pr_warning("Warning: No dwarf info found in the vmlinux - " 507 pr_warning("Warning: No dwarf info found in the vmlinux - "
506 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); 508 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
507 if (!need_dwarf) { 509 if (!need_dwarf) {
508 pr_debug("Trying to use symbols.\n"); 510 pr_debug("Trying to use symbols.\n");
509 return 0; 511 return 0;
510 } 512 }
511 } 513 }
512 return ntevs; 514 return ntevs;
513 } 515 }
514 516
515 /* 517 /*
516 * Find a src file from a DWARF tag path. Prepend optional source path prefix 518 * Find a src file from a DWARF tag path. Prepend optional source path prefix
517 * and chop off leading directories that do not exist. Result is passed back as 519 * and chop off leading directories that do not exist. Result is passed back as
518 * a newly allocated path on success. 520 * a newly allocated path on success.
519 * Return 0 if file was found and readable, -errno otherwise. 521 * Return 0 if file was found and readable, -errno otherwise.
520 */ 522 */
521 static int get_real_path(const char *raw_path, const char *comp_dir, 523 static int get_real_path(const char *raw_path, const char *comp_dir,
522 char **new_path) 524 char **new_path)
523 { 525 {
524 const char *prefix = symbol_conf.source_prefix; 526 const char *prefix = symbol_conf.source_prefix;
525 527
526 if (!prefix) { 528 if (!prefix) {
527 if (raw_path[0] != '/' && comp_dir) 529 if (raw_path[0] != '/' && comp_dir)
528 /* If not an absolute path, try to use comp_dir */ 530 /* If not an absolute path, try to use comp_dir */
529 prefix = comp_dir; 531 prefix = comp_dir;
530 else { 532 else {
531 if (access(raw_path, R_OK) == 0) { 533 if (access(raw_path, R_OK) == 0) {
532 *new_path = strdup(raw_path); 534 *new_path = strdup(raw_path);
533 return 0; 535 return 0;
534 } else 536 } else
535 return -errno; 537 return -errno;
536 } 538 }
537 } 539 }
538 540
539 *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2)); 541 *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2));
540 if (!*new_path) 542 if (!*new_path)
541 return -ENOMEM; 543 return -ENOMEM;
542 544
543 for (;;) { 545 for (;;) {
544 sprintf(*new_path, "%s/%s", prefix, raw_path); 546 sprintf(*new_path, "%s/%s", prefix, raw_path);
545 547
546 if (access(*new_path, R_OK) == 0) 548 if (access(*new_path, R_OK) == 0)
547 return 0; 549 return 0;
548 550
549 if (!symbol_conf.source_prefix) 551 if (!symbol_conf.source_prefix)
550 /* In case of searching comp_dir, don't retry */ 552 /* In case of searching comp_dir, don't retry */
551 return -errno; 553 return -errno;
552 554
553 switch (errno) { 555 switch (errno) {
554 case ENAMETOOLONG: 556 case ENAMETOOLONG:
555 case ENOENT: 557 case ENOENT:
556 case EROFS: 558 case EROFS:
557 case EFAULT: 559 case EFAULT:
558 raw_path = strchr(++raw_path, '/'); 560 raw_path = strchr(++raw_path, '/');
559 if (!raw_path) { 561 if (!raw_path) {
560 zfree(new_path); 562 zfree(new_path);
561 return -ENOENT; 563 return -ENOENT;
562 } 564 }
563 continue; 565 continue;
564 566
565 default: 567 default:
566 zfree(new_path); 568 zfree(new_path);
567 return -errno; 569 return -errno;
568 } 570 }
569 } 571 }
570 } 572 }
571 573
572 #define LINEBUF_SIZE 256 574 #define LINEBUF_SIZE 256
573 #define NR_ADDITIONAL_LINES 2 575 #define NR_ADDITIONAL_LINES 2
574 576
575 static int __show_one_line(FILE *fp, int l, bool skip, bool show_num) 577 static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
576 { 578 {
577 char buf[LINEBUF_SIZE], sbuf[STRERR_BUFSIZE]; 579 char buf[LINEBUF_SIZE], sbuf[STRERR_BUFSIZE];
578 const char *color = show_num ? "" : PERF_COLOR_BLUE; 580 const char *color = show_num ? "" : PERF_COLOR_BLUE;
579 const char *prefix = NULL; 581 const char *prefix = NULL;
580 582
581 do { 583 do {
582 if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 584 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
583 goto error; 585 goto error;
584 if (skip) 586 if (skip)
585 continue; 587 continue;
586 if (!prefix) { 588 if (!prefix) {
587 prefix = show_num ? "%7d " : " "; 589 prefix = show_num ? "%7d " : " ";
588 color_fprintf(stdout, color, prefix, l); 590 color_fprintf(stdout, color, prefix, l);
589 } 591 }
590 color_fprintf(stdout, color, "%s", buf); 592 color_fprintf(stdout, color, "%s", buf);
591 593
592 } while (strchr(buf, '\n') == NULL); 594 } while (strchr(buf, '\n') == NULL);
593 595
594 return 1; 596 return 1;
595 error: 597 error:
596 if (ferror(fp)) { 598 if (ferror(fp)) {
597 pr_warning("File read error: %s\n", 599 pr_warning("File read error: %s\n",
598 strerror_r(errno, sbuf, sizeof(sbuf))); 600 strerror_r(errno, sbuf, sizeof(sbuf)));
599 return -1; 601 return -1;
600 } 602 }
601 return 0; 603 return 0;
602 } 604 }
603 605
604 static int _show_one_line(FILE *fp, int l, bool skip, bool show_num) 606 static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
605 { 607 {
606 int rv = __show_one_line(fp, l, skip, show_num); 608 int rv = __show_one_line(fp, l, skip, show_num);
607 if (rv == 0) { 609 if (rv == 0) {
608 pr_warning("Source file is shorter than expected.\n"); 610 pr_warning("Source file is shorter than expected.\n");
609 rv = -1; 611 rv = -1;
610 } 612 }
611 return rv; 613 return rv;
612 } 614 }
613 615
614 #define show_one_line_with_num(f,l) _show_one_line(f,l,false,true) 616 #define show_one_line_with_num(f,l) _show_one_line(f,l,false,true)
615 #define show_one_line(f,l) _show_one_line(f,l,false,false) 617 #define show_one_line(f,l) _show_one_line(f,l,false,false)
616 #define skip_one_line(f,l) _show_one_line(f,l,true,false) 618 #define skip_one_line(f,l) _show_one_line(f,l,true,false)
617 #define show_one_line_or_eof(f,l) __show_one_line(f,l,false,false) 619 #define show_one_line_or_eof(f,l) __show_one_line(f,l,false,false)
618 620
619 /* 621 /*
620 * Show line-range always requires debuginfo to find source file and 622 * Show line-range always requires debuginfo to find source file and
621 * line number. 623 * line number.
622 */ 624 */
623 static int __show_line_range(struct line_range *lr, const char *module) 625 static int __show_line_range(struct line_range *lr, const char *module)
624 { 626 {
625 int l = 1; 627 int l = 1;
626 struct int_node *ln; 628 struct int_node *ln;
627 struct debuginfo *dinfo; 629 struct debuginfo *dinfo;
628 FILE *fp; 630 FILE *fp;
629 int ret; 631 int ret;
630 char *tmp; 632 char *tmp;
631 char sbuf[STRERR_BUFSIZE]; 633 char sbuf[STRERR_BUFSIZE];
632 634
633 /* Search a line range */ 635 /* Search a line range */
634 dinfo = open_debuginfo(module, false); 636 dinfo = open_debuginfo(module, false);
635 if (!dinfo) 637 if (!dinfo)
636 return -ENOENT; 638 return -ENOENT;
637 639
638 ret = debuginfo__find_line_range(dinfo, lr); 640 ret = debuginfo__find_line_range(dinfo, lr);
639 debuginfo__delete(dinfo); 641 debuginfo__delete(dinfo);
640 if (ret == 0 || ret == -ENOENT) { 642 if (ret == 0 || ret == -ENOENT) {
641 pr_warning("Specified source line is not found.\n"); 643 pr_warning("Specified source line is not found.\n");
642 return -ENOENT; 644 return -ENOENT;
643 } else if (ret < 0) { 645 } else if (ret < 0) {
644 pr_warning("Debuginfo analysis failed.\n"); 646 pr_warning("Debuginfo analysis failed.\n");
645 return ret; 647 return ret;
646 } 648 }
647 649
648 /* Convert source file path */ 650 /* Convert source file path */
649 tmp = lr->path; 651 tmp = lr->path;
650 ret = get_real_path(tmp, lr->comp_dir, &lr->path); 652 ret = get_real_path(tmp, lr->comp_dir, &lr->path);
651 free(tmp); /* Free old path */ 653 free(tmp); /* Free old path */
652 if (ret < 0) { 654 if (ret < 0) {
653 pr_warning("Failed to find source file path.\n"); 655 pr_warning("Failed to find source file path.\n");
654 return ret; 656 return ret;
655 } 657 }
656 658
657 setup_pager(); 659 setup_pager();
658 660
659 if (lr->function) 661 if (lr->function)
660 fprintf(stdout, "<%s@%s:%d>\n", lr->function, lr->path, 662 fprintf(stdout, "<%s@%s:%d>\n", lr->function, lr->path,
661 lr->start - lr->offset); 663 lr->start - lr->offset);
662 else 664 else
663 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start); 665 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
664 666
665 fp = fopen(lr->path, "r"); 667 fp = fopen(lr->path, "r");
666 if (fp == NULL) { 668 if (fp == NULL) {
667 pr_warning("Failed to open %s: %s\n", lr->path, 669 pr_warning("Failed to open %s: %s\n", lr->path,
668 strerror_r(errno, sbuf, sizeof(sbuf))); 670 strerror_r(errno, sbuf, sizeof(sbuf)));
669 return -errno; 671 return -errno;
670 } 672 }
671 /* Skip to starting line number */ 673 /* Skip to starting line number */
672 while (l < lr->start) { 674 while (l < lr->start) {
673 ret = skip_one_line(fp, l++); 675 ret = skip_one_line(fp, l++);
674 if (ret < 0) 676 if (ret < 0)
675 goto end; 677 goto end;
676 } 678 }
677 679
678 intlist__for_each(ln, lr->line_list) { 680 intlist__for_each(ln, lr->line_list) {
679 for (; ln->i > l; l++) { 681 for (; ln->i > l; l++) {
680 ret = show_one_line(fp, l - lr->offset); 682 ret = show_one_line(fp, l - lr->offset);
681 if (ret < 0) 683 if (ret < 0)
682 goto end; 684 goto end;
683 } 685 }
684 ret = show_one_line_with_num(fp, l++ - lr->offset); 686 ret = show_one_line_with_num(fp, l++ - lr->offset);
685 if (ret < 0) 687 if (ret < 0)
686 goto end; 688 goto end;
687 } 689 }
688 690
689 if (lr->end == INT_MAX) 691 if (lr->end == INT_MAX)
690 lr->end = l + NR_ADDITIONAL_LINES; 692 lr->end = l + NR_ADDITIONAL_LINES;
691 while (l <= lr->end) { 693 while (l <= lr->end) {
692 ret = show_one_line_or_eof(fp, l++ - lr->offset); 694 ret = show_one_line_or_eof(fp, l++ - lr->offset);
693 if (ret <= 0) 695 if (ret <= 0)
694 break; 696 break;
695 } 697 }
696 end: 698 end:
697 fclose(fp); 699 fclose(fp);
698 return ret; 700 return ret;
699 } 701 }
700 702
701 int show_line_range(struct line_range *lr, const char *module, bool user) 703 int show_line_range(struct line_range *lr, const char *module, bool user)
702 { 704 {
703 int ret; 705 int ret;
704 706
705 ret = init_symbol_maps(user); 707 ret = init_symbol_maps(user);
706 if (ret < 0) 708 if (ret < 0)
707 return ret; 709 return ret;
708 ret = __show_line_range(lr, module); 710 ret = __show_line_range(lr, module);
709 exit_symbol_maps(); 711 exit_symbol_maps();
710 712
711 return ret; 713 return ret;
712 } 714 }
713 715
714 static int show_available_vars_at(struct debuginfo *dinfo, 716 static int show_available_vars_at(struct debuginfo *dinfo,
715 struct perf_probe_event *pev, 717 struct perf_probe_event *pev,
716 int max_vls, struct strfilter *_filter, 718 int max_vls, struct strfilter *_filter,
717 bool externs) 719 bool externs)
718 { 720 {
719 char *buf; 721 char *buf;
720 int ret, i, nvars; 722 int ret, i, nvars;
721 struct str_node *node; 723 struct str_node *node;
722 struct variable_list *vls = NULL, *vl; 724 struct variable_list *vls = NULL, *vl;
723 const char *var; 725 const char *var;
724 726
725 buf = synthesize_perf_probe_point(&pev->point); 727 buf = synthesize_perf_probe_point(&pev->point);
726 if (!buf) 728 if (!buf)
727 return -EINVAL; 729 return -EINVAL;
728 pr_debug("Searching variables at %s\n", buf); 730 pr_debug("Searching variables at %s\n", buf);
729 731
730 ret = debuginfo__find_available_vars_at(dinfo, pev, &vls, 732 ret = debuginfo__find_available_vars_at(dinfo, pev, &vls,
731 max_vls, externs); 733 max_vls, externs);
732 if (ret <= 0) { 734 if (ret <= 0) {
733 if (ret == 0 || ret == -ENOENT) { 735 if (ret == 0 || ret == -ENOENT) {
734 pr_err("Failed to find the address of %s\n", buf); 736 pr_err("Failed to find the address of %s\n", buf);
735 ret = -ENOENT; 737 ret = -ENOENT;
736 } else 738 } else
737 pr_warning("Debuginfo analysis failed.\n"); 739 pr_warning("Debuginfo analysis failed.\n");
738 goto end; 740 goto end;
739 } 741 }
740 742
741 /* Some variables are found */ 743 /* Some variables are found */
742 fprintf(stdout, "Available variables at %s\n", buf); 744 fprintf(stdout, "Available variables at %s\n", buf);
743 for (i = 0; i < ret; i++) { 745 for (i = 0; i < ret; i++) {
744 vl = &vls[i]; 746 vl = &vls[i];
745 /* 747 /*
746 * A probe point might be converted to 748 * A probe point might be converted to
747 * several trace points. 749 * several trace points.
748 */ 750 */
749 fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, 751 fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol,
750 vl->point.offset); 752 vl->point.offset);
751 zfree(&vl->point.symbol); 753 zfree(&vl->point.symbol);
752 nvars = 0; 754 nvars = 0;
753 if (vl->vars) { 755 if (vl->vars) {
754 strlist__for_each(node, vl->vars) { 756 strlist__for_each(node, vl->vars) {
755 var = strchr(node->s, '\t') + 1; 757 var = strchr(node->s, '\t') + 1;
756 if (strfilter__compare(_filter, var)) { 758 if (strfilter__compare(_filter, var)) {
757 fprintf(stdout, "\t\t%s\n", node->s); 759 fprintf(stdout, "\t\t%s\n", node->s);
758 nvars++; 760 nvars++;
759 } 761 }
760 } 762 }
761 strlist__delete(vl->vars); 763 strlist__delete(vl->vars);
762 } 764 }
763 if (nvars == 0) 765 if (nvars == 0)
764 fprintf(stdout, "\t\t(No matched variables)\n"); 766 fprintf(stdout, "\t\t(No matched variables)\n");
765 } 767 }
766 free(vls); 768 free(vls);
767 end: 769 end:
768 free(buf); 770 free(buf);
769 return ret; 771 return ret;
770 } 772 }
771 773
772 /* Show available variables on given probe point */ 774 /* Show available variables on given probe point */
773 int show_available_vars(struct perf_probe_event *pevs, int npevs, 775 int show_available_vars(struct perf_probe_event *pevs, int npevs,
774 int max_vls, const char *module, 776 int max_vls, const char *module,
775 struct strfilter *_filter, bool externs) 777 struct strfilter *_filter, bool externs)
776 { 778 {
777 int i, ret = 0; 779 int i, ret = 0;
778 struct debuginfo *dinfo; 780 struct debuginfo *dinfo;
779 781
780 ret = init_symbol_maps(pevs->uprobes); 782 ret = init_symbol_maps(pevs->uprobes);
781 if (ret < 0) 783 if (ret < 0)
782 return ret; 784 return ret;
783 785
784 dinfo = open_debuginfo(module, false); 786 dinfo = open_debuginfo(module, false);
785 if (!dinfo) { 787 if (!dinfo) {
786 ret = -ENOENT; 788 ret = -ENOENT;
787 goto out; 789 goto out;
788 } 790 }
789 791
790 setup_pager(); 792 setup_pager();
791 793
792 for (i = 0; i < npevs && ret >= 0; i++) 794 for (i = 0; i < npevs && ret >= 0; i++)
793 ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter, 795 ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
794 externs); 796 externs);
795 797
796 debuginfo__delete(dinfo); 798 debuginfo__delete(dinfo);
797 out: 799 out:
798 exit_symbol_maps(); 800 exit_symbol_maps();
799 return ret; 801 return ret;
800 } 802 }
801 803
802 #else /* !HAVE_DWARF_SUPPORT */ 804 #else /* !HAVE_DWARF_SUPPORT */
803 805
804 static int 806 static int
805 find_perf_probe_point_from_dwarf(struct probe_trace_point *tp __maybe_unused, 807 find_perf_probe_point_from_dwarf(struct probe_trace_point *tp __maybe_unused,
806 struct perf_probe_point *pp __maybe_unused, 808 struct perf_probe_point *pp __maybe_unused,
807 bool is_kprobe __maybe_unused) 809 bool is_kprobe __maybe_unused)
808 { 810 {
809 return -ENOSYS; 811 return -ENOSYS;
810 } 812 }
811 813
812 static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 814 static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
813 struct probe_trace_event **tevs __maybe_unused, 815 struct probe_trace_event **tevs __maybe_unused,
814 int max_tevs __maybe_unused, 816 int max_tevs __maybe_unused,
815 const char *target __maybe_unused) 817 const char *target __maybe_unused)
816 { 818 {
817 if (perf_probe_event_need_dwarf(pev)) { 819 if (perf_probe_event_need_dwarf(pev)) {
818 pr_warning("Debuginfo-analysis is not supported.\n"); 820 pr_warning("Debuginfo-analysis is not supported.\n");
819 return -ENOSYS; 821 return -ENOSYS;
820 } 822 }
821 823
822 return 0; 824 return 0;
823 } 825 }
824 826
825 int show_line_range(struct line_range *lr __maybe_unused, 827 int show_line_range(struct line_range *lr __maybe_unused,
826 const char *module __maybe_unused, 828 const char *module __maybe_unused,
827 bool user __maybe_unused) 829 bool user __maybe_unused)
828 { 830 {
829 pr_warning("Debuginfo-analysis is not supported.\n"); 831 pr_warning("Debuginfo-analysis is not supported.\n");
830 return -ENOSYS; 832 return -ENOSYS;
831 } 833 }
832 834
833 int show_available_vars(struct perf_probe_event *pevs __maybe_unused, 835 int show_available_vars(struct perf_probe_event *pevs __maybe_unused,
834 int npevs __maybe_unused, int max_vls __maybe_unused, 836 int npevs __maybe_unused, int max_vls __maybe_unused,
835 const char *module __maybe_unused, 837 const char *module __maybe_unused,
836 struct strfilter *filter __maybe_unused, 838 struct strfilter *filter __maybe_unused,
837 bool externs __maybe_unused) 839 bool externs __maybe_unused)
838 { 840 {
839 pr_warning("Debuginfo-analysis is not supported.\n"); 841 pr_warning("Debuginfo-analysis is not supported.\n");
840 return -ENOSYS; 842 return -ENOSYS;
841 } 843 }
842 #endif 844 #endif
843 845
844 void line_range__clear(struct line_range *lr) 846 void line_range__clear(struct line_range *lr)
845 { 847 {
846 free(lr->function); 848 free(lr->function);
847 free(lr->file); 849 free(lr->file);
848 free(lr->path); 850 free(lr->path);
849 free(lr->comp_dir); 851 free(lr->comp_dir);
850 intlist__delete(lr->line_list); 852 intlist__delete(lr->line_list);
851 memset(lr, 0, sizeof(*lr)); 853 memset(lr, 0, sizeof(*lr));
852 } 854 }
853 855
854 int line_range__init(struct line_range *lr) 856 int line_range__init(struct line_range *lr)
855 { 857 {
856 memset(lr, 0, sizeof(*lr)); 858 memset(lr, 0, sizeof(*lr));
857 lr->line_list = intlist__new(NULL); 859 lr->line_list = intlist__new(NULL);
858 if (!lr->line_list) 860 if (!lr->line_list)
859 return -ENOMEM; 861 return -ENOMEM;
860 else 862 else
861 return 0; 863 return 0;
862 } 864 }
863 865
864 static int parse_line_num(char **ptr, int *val, const char *what) 866 static int parse_line_num(char **ptr, int *val, const char *what)
865 { 867 {
866 const char *start = *ptr; 868 const char *start = *ptr;
867 869
868 errno = 0; 870 errno = 0;
869 *val = strtol(*ptr, ptr, 0); 871 *val = strtol(*ptr, ptr, 0);
870 if (errno || *ptr == start) { 872 if (errno || *ptr == start) {
871 semantic_error("'%s' is not a valid number.\n", what); 873 semantic_error("'%s' is not a valid number.\n", what);
872 return -EINVAL; 874 return -EINVAL;
873 } 875 }
874 return 0; 876 return 0;
875 } 877 }
876 878
877 /* 879 /*
878 * Stuff 'lr' according to the line range described by 'arg'. 880 * Stuff 'lr' according to the line range described by 'arg'.
879 * The line range syntax is described by: 881 * The line range syntax is described by:
880 * 882 *
881 * SRC[:SLN[+NUM|-ELN]] 883 * SRC[:SLN[+NUM|-ELN]]
882 * FNC[@SRC][:SLN[+NUM|-ELN]] 884 * FNC[@SRC][:SLN[+NUM|-ELN]]
883 */ 885 */
884 int parse_line_range_desc(const char *arg, struct line_range *lr) 886 int parse_line_range_desc(const char *arg, struct line_range *lr)
885 { 887 {
886 char *range, *file, *name = strdup(arg); 888 char *range, *file, *name = strdup(arg);
887 int err; 889 int err;
888 890
889 if (!name) 891 if (!name)
890 return -ENOMEM; 892 return -ENOMEM;
891 893
892 lr->start = 0; 894 lr->start = 0;
893 lr->end = INT_MAX; 895 lr->end = INT_MAX;
894 896
895 range = strchr(name, ':'); 897 range = strchr(name, ':');
896 if (range) { 898 if (range) {
897 *range++ = '\0'; 899 *range++ = '\0';
898 900
899 err = parse_line_num(&range, &lr->start, "start line"); 901 err = parse_line_num(&range, &lr->start, "start line");
900 if (err) 902 if (err)
901 goto err; 903 goto err;
902 904
903 if (*range == '+' || *range == '-') { 905 if (*range == '+' || *range == '-') {
904 const char c = *range++; 906 const char c = *range++;
905 907
906 err = parse_line_num(&range, &lr->end, "end line"); 908 err = parse_line_num(&range, &lr->end, "end line");
907 if (err) 909 if (err)
908 goto err; 910 goto err;
909 911
910 if (c == '+') { 912 if (c == '+') {
911 lr->end += lr->start; 913 lr->end += lr->start;
912 /* 914 /*
913 * Adjust the number of lines here. 915 * Adjust the number of lines here.
914 * If the number of lines == 1, the 916 * If the number of lines == 1, the
915 * the end of line should be equal to 917 * the end of line should be equal to
916 * the start of line. 918 * the start of line.
917 */ 919 */
918 lr->end--; 920 lr->end--;
919 } 921 }
920 } 922 }
921 923
922 pr_debug("Line range is %d to %d\n", lr->start, lr->end); 924 pr_debug("Line range is %d to %d\n", lr->start, lr->end);
923 925
924 err = -EINVAL; 926 err = -EINVAL;
925 if (lr->start > lr->end) { 927 if (lr->start > lr->end) {
926 semantic_error("Start line must be smaller" 928 semantic_error("Start line must be smaller"
927 " than end line.\n"); 929 " than end line.\n");
928 goto err; 930 goto err;
929 } 931 }
930 if (*range != '\0') { 932 if (*range != '\0') {
931 semantic_error("Tailing with invalid str '%s'.\n", range); 933 semantic_error("Tailing with invalid str '%s'.\n", range);
932 goto err; 934 goto err;
933 } 935 }
934 } 936 }
935 937
936 file = strchr(name, '@'); 938 file = strchr(name, '@');
937 if (file) { 939 if (file) {
938 *file = '\0'; 940 *file = '\0';
939 lr->file = strdup(++file); 941 lr->file = strdup(++file);
940 if (lr->file == NULL) { 942 if (lr->file == NULL) {
941 err = -ENOMEM; 943 err = -ENOMEM;
942 goto err; 944 goto err;
943 } 945 }
944 lr->function = name; 946 lr->function = name;
945 } else if (strchr(name, '.')) 947 } else if (strchr(name, '.'))
946 lr->file = name; 948 lr->file = name;
947 else 949 else
948 lr->function = name; 950 lr->function = name;
949 951
950 return 0; 952 return 0;
951 err: 953 err:
952 free(name); 954 free(name);
953 return err; 955 return err;
954 } 956 }
955 957
956 /* Check the name is good for event/group */ 958 /* Check the name is good for event/group */
957 static bool check_event_name(const char *name) 959 static bool check_event_name(const char *name)
958 { 960 {
959 if (!isalpha(*name) && *name != '_') 961 if (!isalpha(*name) && *name != '_')
960 return false; 962 return false;
961 while (*++name != '\0') { 963 while (*++name != '\0') {
962 if (!isalpha(*name) && !isdigit(*name) && *name != '_') 964 if (!isalpha(*name) && !isdigit(*name) && *name != '_')
963 return false; 965 return false;
964 } 966 }
965 return true; 967 return true;
966 } 968 }
967 969
968 /* Parse probepoint definition. */ 970 /* Parse probepoint definition. */
969 static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) 971 static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
970 { 972 {
971 struct perf_probe_point *pp = &pev->point; 973 struct perf_probe_point *pp = &pev->point;
972 char *ptr, *tmp; 974 char *ptr, *tmp;
973 char c, nc = 0; 975 char c, nc = 0;
974 /* 976 /*
975 * <Syntax> 977 * <Syntax>
976 * perf probe [EVENT=]SRC[:LN|;PTN] 978 * perf probe [EVENT=]SRC[:LN|;PTN]
977 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] 979 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
978 * 980 *
979 * TODO:Group name support 981 * TODO:Group name support
980 */ 982 */
981 983
982 ptr = strpbrk(arg, ";=@+%"); 984 ptr = strpbrk(arg, ";=@+%");
983 if (ptr && *ptr == '=') { /* Event name */ 985 if (ptr && *ptr == '=') { /* Event name */
984 *ptr = '\0'; 986 *ptr = '\0';
985 tmp = ptr + 1; 987 tmp = ptr + 1;
986 if (strchr(arg, ':')) { 988 if (strchr(arg, ':')) {
987 semantic_error("Group name is not supported yet.\n"); 989 semantic_error("Group name is not supported yet.\n");
988 return -ENOTSUP; 990 return -ENOTSUP;
989 } 991 }
990 if (!check_event_name(arg)) { 992 if (!check_event_name(arg)) {
991 semantic_error("%s is bad for event name -it must " 993 semantic_error("%s is bad for event name -it must "
992 "follow C symbol-naming rule.\n", arg); 994 "follow C symbol-naming rule.\n", arg);
993 return -EINVAL; 995 return -EINVAL;
994 } 996 }
995 pev->event = strdup(arg); 997 pev->event = strdup(arg);
996 if (pev->event == NULL) 998 if (pev->event == NULL)
997 return -ENOMEM; 999 return -ENOMEM;
998 pev->group = NULL; 1000 pev->group = NULL;
999 arg = tmp; 1001 arg = tmp;
1000 } 1002 }
1001 1003
1002 ptr = strpbrk(arg, ";:+@%"); 1004 ptr = strpbrk(arg, ";:+@%");
1003 if (ptr) { 1005 if (ptr) {
1004 nc = *ptr; 1006 nc = *ptr;
1005 *ptr++ = '\0'; 1007 *ptr++ = '\0';
1006 } 1008 }
1007 1009
1008 tmp = strdup(arg); 1010 tmp = strdup(arg);
1009 if (tmp == NULL) 1011 if (tmp == NULL)
1010 return -ENOMEM; 1012 return -ENOMEM;
1011 1013
1012 /* Check arg is function or file and copy it */ 1014 /* Check arg is function or file and copy it */
1013 if (strchr(tmp, '.')) /* File */ 1015 if (strchr(tmp, '.')) /* File */
1014 pp->file = tmp; 1016 pp->file = tmp;
1015 else /* Function */ 1017 else /* Function */
1016 pp->function = tmp; 1018 pp->function = tmp;
1017 1019
1018 /* Parse other options */ 1020 /* Parse other options */
1019 while (ptr) { 1021 while (ptr) {
1020 arg = ptr; 1022 arg = ptr;
1021 c = nc; 1023 c = nc;
1022 if (c == ';') { /* Lazy pattern must be the last part */ 1024 if (c == ';') { /* Lazy pattern must be the last part */
1023 pp->lazy_line = strdup(arg); 1025 pp->lazy_line = strdup(arg);
1024 if (pp->lazy_line == NULL) 1026 if (pp->lazy_line == NULL)
1025 return -ENOMEM; 1027 return -ENOMEM;
1026 break; 1028 break;
1027 } 1029 }
1028 ptr = strpbrk(arg, ";:+@%"); 1030 ptr = strpbrk(arg, ";:+@%");
1029 if (ptr) { 1031 if (ptr) {
1030 nc = *ptr; 1032 nc = *ptr;
1031 *ptr++ = '\0'; 1033 *ptr++ = '\0';
1032 } 1034 }
1033 switch (c) { 1035 switch (c) {
1034 case ':': /* Line number */ 1036 case ':': /* Line number */
1035 pp->line = strtoul(arg, &tmp, 0); 1037 pp->line = strtoul(arg, &tmp, 0);
1036 if (*tmp != '\0') { 1038 if (*tmp != '\0') {
1037 semantic_error("There is non-digit char" 1039 semantic_error("There is non-digit char"
1038 " in line number.\n"); 1040 " in line number.\n");
1039 return -EINVAL; 1041 return -EINVAL;
1040 } 1042 }
1041 break; 1043 break;
1042 case '+': /* Byte offset from a symbol */ 1044 case '+': /* Byte offset from a symbol */
1043 pp->offset = strtoul(arg, &tmp, 0); 1045 pp->offset = strtoul(arg, &tmp, 0);
1044 if (*tmp != '\0') { 1046 if (*tmp != '\0') {
1045 semantic_error("There is non-digit character" 1047 semantic_error("There is non-digit character"
1046 " in offset.\n"); 1048 " in offset.\n");
1047 return -EINVAL; 1049 return -EINVAL;
1048 } 1050 }
1049 break; 1051 break;
1050 case '@': /* File name */ 1052 case '@': /* File name */
1051 if (pp->file) { 1053 if (pp->file) {
1052 semantic_error("SRC@SRC is not allowed.\n"); 1054 semantic_error("SRC@SRC is not allowed.\n");
1053 return -EINVAL; 1055 return -EINVAL;
1054 } 1056 }
1055 pp->file = strdup(arg); 1057 pp->file = strdup(arg);
1056 if (pp->file == NULL) 1058 if (pp->file == NULL)
1057 return -ENOMEM; 1059 return -ENOMEM;
1058 break; 1060 break;
1059 case '%': /* Probe places */ 1061 case '%': /* Probe places */
1060 if (strcmp(arg, "return") == 0) { 1062 if (strcmp(arg, "return") == 0) {
1061 pp->retprobe = 1; 1063 pp->retprobe = 1;
1062 } else { /* Others not supported yet */ 1064 } else { /* Others not supported yet */
1063 semantic_error("%%%s is not supported.\n", arg); 1065 semantic_error("%%%s is not supported.\n", arg);
1064 return -ENOTSUP; 1066 return -ENOTSUP;
1065 } 1067 }
1066 break; 1068 break;
1067 default: /* Buggy case */ 1069 default: /* Buggy case */
1068 pr_err("This program has a bug at %s:%d.\n", 1070 pr_err("This program has a bug at %s:%d.\n",
1069 __FILE__, __LINE__); 1071 __FILE__, __LINE__);
1070 return -ENOTSUP; 1072 return -ENOTSUP;
1071 break; 1073 break;
1072 } 1074 }
1073 } 1075 }
1074 1076
1075 /* Exclusion check */ 1077 /* Exclusion check */
1076 if (pp->lazy_line && pp->line) { 1078 if (pp->lazy_line && pp->line) {
1077 semantic_error("Lazy pattern can't be used with" 1079 semantic_error("Lazy pattern can't be used with"
1078 " line number.\n"); 1080 " line number.\n");
1079 return -EINVAL; 1081 return -EINVAL;
1080 } 1082 }
1081 1083
1082 if (pp->lazy_line && pp->offset) { 1084 if (pp->lazy_line && pp->offset) {
1083 semantic_error("Lazy pattern can't be used with offset.\n"); 1085 semantic_error("Lazy pattern can't be used with offset.\n");
1084 return -EINVAL; 1086 return -EINVAL;
1085 } 1087 }
1086 1088
1087 if (pp->line && pp->offset) { 1089 if (pp->line && pp->offset) {
1088 semantic_error("Offset can't be used with line number.\n"); 1090 semantic_error("Offset can't be used with line number.\n");
1089 return -EINVAL; 1091 return -EINVAL;
1090 } 1092 }
1091 1093
1092 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) { 1094 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
1093 semantic_error("File always requires line number or " 1095 semantic_error("File always requires line number or "
1094 "lazy pattern.\n"); 1096 "lazy pattern.\n");
1095 return -EINVAL; 1097 return -EINVAL;
1096 } 1098 }
1097 1099
1098 if (pp->offset && !pp->function) { 1100 if (pp->offset && !pp->function) {
1099 semantic_error("Offset requires an entry function.\n"); 1101 semantic_error("Offset requires an entry function.\n");
1100 return -EINVAL; 1102 return -EINVAL;
1101 } 1103 }
1102 1104
1103 if (pp->retprobe && !pp->function) { 1105 if (pp->retprobe && !pp->function) {
1104 semantic_error("Return probe requires an entry function.\n"); 1106 semantic_error("Return probe requires an entry function.\n");
1105 return -EINVAL; 1107 return -EINVAL;
1106 } 1108 }
1107 1109
1108 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) { 1110 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
1109 semantic_error("Offset/Line/Lazy pattern can't be used with " 1111 semantic_error("Offset/Line/Lazy pattern can't be used with "
1110 "return probe.\n"); 1112 "return probe.\n");
1111 return -EINVAL; 1113 return -EINVAL;
1112 } 1114 }
1113 1115
1114 pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n", 1116 pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n",
1115 pp->function, pp->file, pp->line, pp->offset, pp->retprobe, 1117 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
1116 pp->lazy_line); 1118 pp->lazy_line);
1117 return 0; 1119 return 0;
1118 } 1120 }
1119 1121
1120 /* Parse perf-probe event argument */ 1122 /* Parse perf-probe event argument */
1121 static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) 1123 static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
1122 { 1124 {
1123 char *tmp, *goodname; 1125 char *tmp, *goodname;
1124 struct perf_probe_arg_field **fieldp; 1126 struct perf_probe_arg_field **fieldp;
1125 1127
1126 pr_debug("parsing arg: %s into ", str); 1128 pr_debug("parsing arg: %s into ", str);
1127 1129
1128 tmp = strchr(str, '='); 1130 tmp = strchr(str, '=');
1129 if (tmp) { 1131 if (tmp) {
1130 arg->name = strndup(str, tmp - str); 1132 arg->name = strndup(str, tmp - str);
1131 if (arg->name == NULL) 1133 if (arg->name == NULL)
1132 return -ENOMEM; 1134 return -ENOMEM;
1133 pr_debug("name:%s ", arg->name); 1135 pr_debug("name:%s ", arg->name);
1134 str = tmp + 1; 1136 str = tmp + 1;
1135 } 1137 }
1136 1138
1137 tmp = strchr(str, ':'); 1139 tmp = strchr(str, ':');
1138 if (tmp) { /* Type setting */ 1140 if (tmp) { /* Type setting */
1139 *tmp = '\0'; 1141 *tmp = '\0';
1140 arg->type = strdup(tmp + 1); 1142 arg->type = strdup(tmp + 1);
1141 if (arg->type == NULL) 1143 if (arg->type == NULL)
1142 return -ENOMEM; 1144 return -ENOMEM;
1143 pr_debug("type:%s ", arg->type); 1145 pr_debug("type:%s ", arg->type);
1144 } 1146 }
1145 1147
1146 tmp = strpbrk(str, "-.["); 1148 tmp = strpbrk(str, "-.[");
1147 if (!is_c_varname(str) || !tmp) { 1149 if (!is_c_varname(str) || !tmp) {
1148 /* A variable, register, symbol or special value */ 1150 /* A variable, register, symbol or special value */
1149 arg->var = strdup(str); 1151 arg->var = strdup(str);
1150 if (arg->var == NULL) 1152 if (arg->var == NULL)
1151 return -ENOMEM; 1153 return -ENOMEM;
1152 pr_debug("%s\n", arg->var); 1154 pr_debug("%s\n", arg->var);
1153 return 0; 1155 return 0;
1154 } 1156 }
1155 1157
1156 /* Structure fields or array element */ 1158 /* Structure fields or array element */
1157 arg->var = strndup(str, tmp - str); 1159 arg->var = strndup(str, tmp - str);
1158 if (arg->var == NULL) 1160 if (arg->var == NULL)
1159 return -ENOMEM; 1161 return -ENOMEM;
1160 goodname = arg->var; 1162 goodname = arg->var;
1161 pr_debug("%s, ", arg->var); 1163 pr_debug("%s, ", arg->var);
1162 fieldp = &arg->field; 1164 fieldp = &arg->field;
1163 1165
1164 do { 1166 do {
1165 *fieldp = zalloc(sizeof(struct perf_probe_arg_field)); 1167 *fieldp = zalloc(sizeof(struct perf_probe_arg_field));
1166 if (*fieldp == NULL) 1168 if (*fieldp == NULL)
1167 return -ENOMEM; 1169 return -ENOMEM;
1168 if (*tmp == '[') { /* Array */ 1170 if (*tmp == '[') { /* Array */
1169 str = tmp; 1171 str = tmp;
1170 (*fieldp)->index = strtol(str + 1, &tmp, 0); 1172 (*fieldp)->index = strtol(str + 1, &tmp, 0);
1171 (*fieldp)->ref = true; 1173 (*fieldp)->ref = true;
1172 if (*tmp != ']' || tmp == str + 1) { 1174 if (*tmp != ']' || tmp == str + 1) {
1173 semantic_error("Array index must be a" 1175 semantic_error("Array index must be a"
1174 " number.\n"); 1176 " number.\n");
1175 return -EINVAL; 1177 return -EINVAL;
1176 } 1178 }
1177 tmp++; 1179 tmp++;
1178 if (*tmp == '\0') 1180 if (*tmp == '\0')
1179 tmp = NULL; 1181 tmp = NULL;
1180 } else { /* Structure */ 1182 } else { /* Structure */
1181 if (*tmp == '.') { 1183 if (*tmp == '.') {
1182 str = tmp + 1; 1184 str = tmp + 1;
1183 (*fieldp)->ref = false; 1185 (*fieldp)->ref = false;
1184 } else if (tmp[1] == '>') { 1186 } else if (tmp[1] == '>') {
1185 str = tmp + 2; 1187 str = tmp + 2;
1186 (*fieldp)->ref = true; 1188 (*fieldp)->ref = true;
1187 } else { 1189 } else {
1188 semantic_error("Argument parse error: %s\n", 1190 semantic_error("Argument parse error: %s\n",
1189 str); 1191 str);
1190 return -EINVAL; 1192 return -EINVAL;
1191 } 1193 }
1192 tmp = strpbrk(str, "-.["); 1194 tmp = strpbrk(str, "-.[");
1193 } 1195 }
1194 if (tmp) { 1196 if (tmp) {
1195 (*fieldp)->name = strndup(str, tmp - str); 1197 (*fieldp)->name = strndup(str, tmp - str);
1196 if ((*fieldp)->name == NULL) 1198 if ((*fieldp)->name == NULL)
1197 return -ENOMEM; 1199 return -ENOMEM;
1198 if (*str != '[') 1200 if (*str != '[')
1199 goodname = (*fieldp)->name; 1201 goodname = (*fieldp)->name;
1200 pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref); 1202 pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref);
1201 fieldp = &(*fieldp)->next; 1203 fieldp = &(*fieldp)->next;
1202 } 1204 }
1203 } while (tmp); 1205 } while (tmp);
1204 (*fieldp)->name = strdup(str); 1206 (*fieldp)->name = strdup(str);
1205 if ((*fieldp)->name == NULL) 1207 if ((*fieldp)->name == NULL)
1206 return -ENOMEM; 1208 return -ENOMEM;
1207 if (*str != '[') 1209 if (*str != '[')
1208 goodname = (*fieldp)->name; 1210 goodname = (*fieldp)->name;
1209 pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref); 1211 pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref);
1210 1212
1211 /* If no name is specified, set the last field name (not array index)*/ 1213 /* If no name is specified, set the last field name (not array index)*/
1212 if (!arg->name) { 1214 if (!arg->name) {
1213 arg->name = strdup(goodname); 1215 arg->name = strdup(goodname);
1214 if (arg->name == NULL) 1216 if (arg->name == NULL)
1215 return -ENOMEM; 1217 return -ENOMEM;
1216 } 1218 }
1217 return 0; 1219 return 0;
1218 } 1220 }
1219 1221
1220 /* Parse perf-probe event command */ 1222 /* Parse perf-probe event command */
1221 int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev) 1223 int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev)
1222 { 1224 {
1223 char **argv; 1225 char **argv;
1224 int argc, i, ret = 0; 1226 int argc, i, ret = 0;
1225 1227
1226 argv = argv_split(cmd, &argc); 1228 argv = argv_split(cmd, &argc);
1227 if (!argv) { 1229 if (!argv) {
1228 pr_debug("Failed to split arguments.\n"); 1230 pr_debug("Failed to split arguments.\n");
1229 return -ENOMEM; 1231 return -ENOMEM;
1230 } 1232 }
1231 if (argc - 1 > MAX_PROBE_ARGS) { 1233 if (argc - 1 > MAX_PROBE_ARGS) {
1232 semantic_error("Too many probe arguments (%d).\n", argc - 1); 1234 semantic_error("Too many probe arguments (%d).\n", argc - 1);
1233 ret = -ERANGE; 1235 ret = -ERANGE;
1234 goto out; 1236 goto out;
1235 } 1237 }
1236 /* Parse probe point */ 1238 /* Parse probe point */
1237 ret = parse_perf_probe_point(argv[0], pev); 1239 ret = parse_perf_probe_point(argv[0], pev);
1238 if (ret < 0) 1240 if (ret < 0)
1239 goto out; 1241 goto out;
1240 1242
1241 /* Copy arguments and ensure return probe has no C argument */ 1243 /* Copy arguments and ensure return probe has no C argument */
1242 pev->nargs = argc - 1; 1244 pev->nargs = argc - 1;
1243 pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs); 1245 pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
1244 if (pev->args == NULL) { 1246 if (pev->args == NULL) {
1245 ret = -ENOMEM; 1247 ret = -ENOMEM;
1246 goto out; 1248 goto out;
1247 } 1249 }
1248 for (i = 0; i < pev->nargs && ret >= 0; i++) { 1250 for (i = 0; i < pev->nargs && ret >= 0; i++) {
1249 ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]); 1251 ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]);
1250 if (ret >= 0 && 1252 if (ret >= 0 &&
1251 is_c_varname(pev->args[i].var) && pev->point.retprobe) { 1253 is_c_varname(pev->args[i].var) && pev->point.retprobe) {
1252 semantic_error("You can't specify local variable for" 1254 semantic_error("You can't specify local variable for"
1253 " kretprobe.\n"); 1255 " kretprobe.\n");
1254 ret = -EINVAL; 1256 ret = -EINVAL;
1255 } 1257 }
1256 } 1258 }
1257 out: 1259 out:
1258 argv_free(argv); 1260 argv_free(argv);
1259 1261
1260 return ret; 1262 return ret;
1261 } 1263 }
1262 1264
1263 /* Return true if this perf_probe_event requires debuginfo */ 1265 /* Return true if this perf_probe_event requires debuginfo */
1264 bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) 1266 bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
1265 { 1267 {
1266 int i; 1268 int i;
1267 1269
1268 if (pev->point.file || pev->point.line || pev->point.lazy_line) 1270 if (pev->point.file || pev->point.line || pev->point.lazy_line)
1269 return true; 1271 return true;
1270 1272
1271 for (i = 0; i < pev->nargs; i++) 1273 for (i = 0; i < pev->nargs; i++)
1272 if (is_c_varname(pev->args[i].var)) 1274 if (is_c_varname(pev->args[i].var))
1273 return true; 1275 return true;
1274 1276
1275 return false; 1277 return false;
1276 } 1278 }
1277 1279
1278 /* Parse probe_events event into struct probe_point */ 1280 /* Parse probe_events event into struct probe_point */
1279 static int parse_probe_trace_command(const char *cmd, 1281 static int parse_probe_trace_command(const char *cmd,
1280 struct probe_trace_event *tev) 1282 struct probe_trace_event *tev)
1281 { 1283 {
1282 struct probe_trace_point *tp = &tev->point; 1284 struct probe_trace_point *tp = &tev->point;
1283 char pr; 1285 char pr;
1284 char *p; 1286 char *p;
1285 char *argv0_str = NULL, *fmt, *fmt1_str, *fmt2_str, *fmt3_str; 1287 char *argv0_str = NULL, *fmt, *fmt1_str, *fmt2_str, *fmt3_str;
1286 int ret, i, argc; 1288 int ret, i, argc;
1287 char **argv; 1289 char **argv;
1288 1290
1289 pr_debug("Parsing probe_events: %s\n", cmd); 1291 pr_debug("Parsing probe_events: %s\n", cmd);
1290 argv = argv_split(cmd, &argc); 1292 argv = argv_split(cmd, &argc);
1291 if (!argv) { 1293 if (!argv) {
1292 pr_debug("Failed to split arguments.\n"); 1294 pr_debug("Failed to split arguments.\n");
1293 return -ENOMEM; 1295 return -ENOMEM;
1294 } 1296 }
1295 if (argc < 2) { 1297 if (argc < 2) {
1296 semantic_error("Too few probe arguments.\n"); 1298 semantic_error("Too few probe arguments.\n");
1297 ret = -ERANGE; 1299 ret = -ERANGE;
1298 goto out; 1300 goto out;
1299 } 1301 }
1300 1302
1301 /* Scan event and group name. */ 1303 /* Scan event and group name. */
1302 argv0_str = strdup(argv[0]); 1304 argv0_str = strdup(argv[0]);
1303 if (argv0_str == NULL) { 1305 if (argv0_str == NULL) {
1304 ret = -ENOMEM; 1306 ret = -ENOMEM;
1305 goto out; 1307 goto out;
1306 } 1308 }
1307 fmt1_str = strtok_r(argv0_str, ":", &fmt); 1309 fmt1_str = strtok_r(argv0_str, ":", &fmt);
1308 fmt2_str = strtok_r(NULL, "/", &fmt); 1310 fmt2_str = strtok_r(NULL, "/", &fmt);
1309 fmt3_str = strtok_r(NULL, " \t", &fmt); 1311 fmt3_str = strtok_r(NULL, " \t", &fmt);
1310 if (fmt1_str == NULL || strlen(fmt1_str) != 1 || fmt2_str == NULL 1312 if (fmt1_str == NULL || strlen(fmt1_str) != 1 || fmt2_str == NULL
1311 || fmt3_str == NULL) { 1313 || fmt3_str == NULL) {
1312 semantic_error("Failed to parse event name: %s\n", argv[0]); 1314 semantic_error("Failed to parse event name: %s\n", argv[0]);
1313 ret = -EINVAL; 1315 ret = -EINVAL;
1314 goto out; 1316 goto out;
1315 } 1317 }
1316 pr = fmt1_str[0]; 1318 pr = fmt1_str[0];
1317 tev->group = strdup(fmt2_str); 1319 tev->group = strdup(fmt2_str);
1318 tev->event = strdup(fmt3_str); 1320 tev->event = strdup(fmt3_str);
1319 if (tev->group == NULL || tev->event == NULL) { 1321 if (tev->group == NULL || tev->event == NULL) {
1320 ret = -ENOMEM; 1322 ret = -ENOMEM;
1321 goto out; 1323 goto out;
1322 } 1324 }
1323 pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr); 1325 pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr);
1324 1326
1325 tp->retprobe = (pr == 'r'); 1327 tp->retprobe = (pr == 'r');
1326 1328
1327 /* Scan module name(if there), function name and offset */ 1329 /* Scan module name(if there), function name and offset */
1328 p = strchr(argv[1], ':'); 1330 p = strchr(argv[1], ':');
1329 if (p) { 1331 if (p) {
1330 tp->module = strndup(argv[1], p - argv[1]); 1332 tp->module = strndup(argv[1], p - argv[1]);
1331 p++; 1333 p++;
1332 } else 1334 } else
1333 p = argv[1]; 1335 p = argv[1];
1334 fmt1_str = strtok_r(p, "+", &fmt); 1336 fmt1_str = strtok_r(p, "+", &fmt);
1335 if (fmt1_str[0] == '0') /* only the address started with 0x */ 1337 if (fmt1_str[0] == '0') /* only the address started with 0x */
1336 tp->address = strtoul(fmt1_str, NULL, 0); 1338 tp->address = strtoul(fmt1_str, NULL, 0);
1337 else { 1339 else {
1338 /* Only the symbol-based probe has offset */ 1340 /* Only the symbol-based probe has offset */
1339 tp->symbol = strdup(fmt1_str); 1341 tp->symbol = strdup(fmt1_str);
1340 if (tp->symbol == NULL) { 1342 if (tp->symbol == NULL) {
1341 ret = -ENOMEM; 1343 ret = -ENOMEM;
1342 goto out; 1344 goto out;
1343 } 1345 }
1344 fmt2_str = strtok_r(NULL, "", &fmt); 1346 fmt2_str = strtok_r(NULL, "", &fmt);
1345 if (fmt2_str == NULL) 1347 if (fmt2_str == NULL)
1346 tp->offset = 0; 1348 tp->offset = 0;
1347 else 1349 else
1348 tp->offset = strtoul(fmt2_str, NULL, 10); 1350 tp->offset = strtoul(fmt2_str, NULL, 10);
1349 } 1351 }
1350 1352
1351 tev->nargs = argc - 2; 1353 tev->nargs = argc - 2;
1352 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); 1354 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
1353 if (tev->args == NULL) { 1355 if (tev->args == NULL) {
1354 ret = -ENOMEM; 1356 ret = -ENOMEM;
1355 goto out; 1357 goto out;
1356 } 1358 }
1357 for (i = 0; i < tev->nargs; i++) { 1359 for (i = 0; i < tev->nargs; i++) {
1358 p = strchr(argv[i + 2], '='); 1360 p = strchr(argv[i + 2], '=');
1359 if (p) /* We don't need which register is assigned. */ 1361 if (p) /* We don't need which register is assigned. */
1360 *p++ = '\0'; 1362 *p++ = '\0';
1361 else 1363 else
1362 p = argv[i + 2]; 1364 p = argv[i + 2];
1363 tev->args[i].name = strdup(argv[i + 2]); 1365 tev->args[i].name = strdup(argv[i + 2]);
1364 /* TODO: parse regs and offset */ 1366 /* TODO: parse regs and offset */
1365 tev->args[i].value = strdup(p); 1367 tev->args[i].value = strdup(p);
1366 if (tev->args[i].name == NULL || tev->args[i].value == NULL) { 1368 if (tev->args[i].name == NULL || tev->args[i].value == NULL) {
1367 ret = -ENOMEM; 1369 ret = -ENOMEM;
1368 goto out; 1370 goto out;
1369 } 1371 }
1370 } 1372 }
1371 ret = 0; 1373 ret = 0;
1372 out: 1374 out:
1373 free(argv0_str); 1375 free(argv0_str);
1374 argv_free(argv); 1376 argv_free(argv);
1375 return ret; 1377 return ret;
1376 } 1378 }
1377 1379
1378 /* Compose only probe arg */ 1380 /* Compose only probe arg */
1379 int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len) 1381 int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
1380 { 1382 {
1381 struct perf_probe_arg_field *field = pa->field; 1383 struct perf_probe_arg_field *field = pa->field;
1382 int ret; 1384 int ret;
1383 char *tmp = buf; 1385 char *tmp = buf;
1384 1386
1385 if (pa->name && pa->var) 1387 if (pa->name && pa->var)
1386 ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var); 1388 ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var);
1387 else 1389 else
1388 ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var); 1390 ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var);
1389 if (ret <= 0) 1391 if (ret <= 0)
1390 goto error; 1392 goto error;
1391 tmp += ret; 1393 tmp += ret;
1392 len -= ret; 1394 len -= ret;
1393 1395
1394 while (field) { 1396 while (field) {
1395 if (field->name[0] == '[') 1397 if (field->name[0] == '[')
1396 ret = e_snprintf(tmp, len, "%s", field->name); 1398 ret = e_snprintf(tmp, len, "%s", field->name);
1397 else 1399 else
1398 ret = e_snprintf(tmp, len, "%s%s", 1400 ret = e_snprintf(tmp, len, "%s%s",
1399 field->ref ? "->" : ".", field->name); 1401 field->ref ? "->" : ".", field->name);
1400 if (ret <= 0) 1402 if (ret <= 0)
1401 goto error; 1403 goto error;
1402 tmp += ret; 1404 tmp += ret;
1403 len -= ret; 1405 len -= ret;
1404 field = field->next; 1406 field = field->next;
1405 } 1407 }
1406 1408
1407 if (pa->type) { 1409 if (pa->type) {
1408 ret = e_snprintf(tmp, len, ":%s", pa->type); 1410 ret = e_snprintf(tmp, len, ":%s", pa->type);
1409 if (ret <= 0) 1411 if (ret <= 0)
1410 goto error; 1412 goto error;
1411 tmp += ret; 1413 tmp += ret;
1412 len -= ret; 1414 len -= ret;
1413 } 1415 }
1414 1416
1415 return tmp - buf; 1417 return tmp - buf;
1416 error: 1418 error:
1417 pr_debug("Failed to synthesize perf probe argument: %d\n", ret); 1419 pr_debug("Failed to synthesize perf probe argument: %d\n", ret);
1418 return ret; 1420 return ret;
1419 } 1421 }
1420 1422
1421 /* Compose only probe point (not argument) */ 1423 /* Compose only probe point (not argument) */
1422 static char *synthesize_perf_probe_point(struct perf_probe_point *pp) 1424 static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1423 { 1425 {
1424 char *buf, *tmp; 1426 char *buf, *tmp;
1425 char offs[32] = "", line[32] = "", file[32] = ""; 1427 char offs[32] = "", line[32] = "", file[32] = "";
1426 int ret, len; 1428 int ret, len;
1427 1429
1428 buf = zalloc(MAX_CMDLEN); 1430 buf = zalloc(MAX_CMDLEN);
1429 if (buf == NULL) { 1431 if (buf == NULL) {
1430 ret = -ENOMEM; 1432 ret = -ENOMEM;
1431 goto error; 1433 goto error;
1432 } 1434 }
1433 if (pp->offset) { 1435 if (pp->offset) {
1434 ret = e_snprintf(offs, 32, "+%lu", pp->offset); 1436 ret = e_snprintf(offs, 32, "+%lu", pp->offset);
1435 if (ret <= 0) 1437 if (ret <= 0)
1436 goto error; 1438 goto error;
1437 } 1439 }
1438 if (pp->line) { 1440 if (pp->line) {
1439 ret = e_snprintf(line, 32, ":%d", pp->line); 1441 ret = e_snprintf(line, 32, ":%d", pp->line);
1440 if (ret <= 0) 1442 if (ret <= 0)
1441 goto error; 1443 goto error;
1442 } 1444 }
1443 if (pp->file) { 1445 if (pp->file) {
1444 tmp = pp->file; 1446 tmp = pp->file;
1445 len = strlen(tmp); 1447 len = strlen(tmp);
1446 if (len > 30) { 1448 if (len > 30) {
1447 tmp = strchr(pp->file + len - 30, '/'); 1449 tmp = strchr(pp->file + len - 30, '/');
1448 tmp = tmp ? tmp + 1 : pp->file + len - 30; 1450 tmp = tmp ? tmp + 1 : pp->file + len - 30;
1449 } 1451 }
1450 ret = e_snprintf(file, 32, "@%s", tmp); 1452 ret = e_snprintf(file, 32, "@%s", tmp);
1451 if (ret <= 0) 1453 if (ret <= 0)
1452 goto error; 1454 goto error;
1453 } 1455 }
1454 1456
1455 if (pp->function) 1457 if (pp->function)
1456 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function, 1458 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function,
1457 offs, pp->retprobe ? "%return" : "", line, 1459 offs, pp->retprobe ? "%return" : "", line,
1458 file); 1460 file);
1459 else 1461 else
1460 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line); 1462 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line);
1461 if (ret <= 0) 1463 if (ret <= 0)
1462 goto error; 1464 goto error;
1463 1465
1464 return buf; 1466 return buf;
1465 error: 1467 error:
1466 pr_debug("Failed to synthesize perf probe point: %d\n", ret); 1468 pr_debug("Failed to synthesize perf probe point: %d\n", ret);
1467 free(buf); 1469 free(buf);
1468 return NULL; 1470 return NULL;
1469 } 1471 }
1470 1472
1471 #if 0 1473 #if 0
1472 char *synthesize_perf_probe_command(struct perf_probe_event *pev) 1474 char *synthesize_perf_probe_command(struct perf_probe_event *pev)
1473 { 1475 {
1474 char *buf; 1476 char *buf;
1475 int i, len, ret; 1477 int i, len, ret;
1476 1478
1477 buf = synthesize_perf_probe_point(&pev->point); 1479 buf = synthesize_perf_probe_point(&pev->point);
1478 if (!buf) 1480 if (!buf)
1479 return NULL; 1481 return NULL;
1480 1482
1481 len = strlen(buf); 1483 len = strlen(buf);
1482 for (i = 0; i < pev->nargs; i++) { 1484 for (i = 0; i < pev->nargs; i++) {
1483 ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s", 1485 ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
1484 pev->args[i].name); 1486 pev->args[i].name);
1485 if (ret <= 0) { 1487 if (ret <= 0) {
1486 free(buf); 1488 free(buf);
1487 return NULL; 1489 return NULL;
1488 } 1490 }
1489 len += ret; 1491 len += ret;
1490 } 1492 }
1491 1493
1492 return buf; 1494 return buf;
1493 } 1495 }
1494 #endif 1496 #endif
1495 1497
1496 static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref, 1498 static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
1497 char **buf, size_t *buflen, 1499 char **buf, size_t *buflen,
1498 int depth) 1500 int depth)
1499 { 1501 {
1500 int ret; 1502 int ret;
1501 if (ref->next) { 1503 if (ref->next) {
1502 depth = __synthesize_probe_trace_arg_ref(ref->next, buf, 1504 depth = __synthesize_probe_trace_arg_ref(ref->next, buf,
1503 buflen, depth + 1); 1505 buflen, depth + 1);
1504 if (depth < 0) 1506 if (depth < 0)
1505 goto out; 1507 goto out;
1506 } 1508 }
1507 1509
1508 ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset); 1510 ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset);
1509 if (ret < 0) 1511 if (ret < 0)
1510 depth = ret; 1512 depth = ret;
1511 else { 1513 else {
1512 *buf += ret; 1514 *buf += ret;
1513 *buflen -= ret; 1515 *buflen -= ret;
1514 } 1516 }
1515 out: 1517 out:
1516 return depth; 1518 return depth;
1517 1519
1518 } 1520 }
1519 1521
1520 static int synthesize_probe_trace_arg(struct probe_trace_arg *arg, 1522 static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
1521 char *buf, size_t buflen) 1523 char *buf, size_t buflen)
1522 { 1524 {
1523 struct probe_trace_arg_ref *ref = arg->ref; 1525 struct probe_trace_arg_ref *ref = arg->ref;
1524 int ret, depth = 0; 1526 int ret, depth = 0;
1525 char *tmp = buf; 1527 char *tmp = buf;
1526 1528
1527 /* Argument name or separator */ 1529 /* Argument name or separator */
1528 if (arg->name) 1530 if (arg->name)
1529 ret = e_snprintf(buf, buflen, " %s=", arg->name); 1531 ret = e_snprintf(buf, buflen, " %s=", arg->name);
1530 else 1532 else
1531 ret = e_snprintf(buf, buflen, " "); 1533 ret = e_snprintf(buf, buflen, " ");
1532 if (ret < 0) 1534 if (ret < 0)
1533 return ret; 1535 return ret;
1534 buf += ret; 1536 buf += ret;
1535 buflen -= ret; 1537 buflen -= ret;
1536 1538
1537 /* Special case: @XXX */ 1539 /* Special case: @XXX */
1538 if (arg->value[0] == '@' && arg->ref) 1540 if (arg->value[0] == '@' && arg->ref)
1539 ref = ref->next; 1541 ref = ref->next;
1540 1542
1541 /* Dereferencing arguments */ 1543 /* Dereferencing arguments */
1542 if (ref) { 1544 if (ref) {
1543 depth = __synthesize_probe_trace_arg_ref(ref, &buf, 1545 depth = __synthesize_probe_trace_arg_ref(ref, &buf,
1544 &buflen, 1); 1546 &buflen, 1);
1545 if (depth < 0) 1547 if (depth < 0)
1546 return depth; 1548 return depth;
1547 } 1549 }
1548 1550
1549 /* Print argument value */ 1551 /* Print argument value */
1550 if (arg->value[0] == '@' && arg->ref) 1552 if (arg->value[0] == '@' && arg->ref)
1551 ret = e_snprintf(buf, buflen, "%s%+ld", arg->value, 1553 ret = e_snprintf(buf, buflen, "%s%+ld", arg->value,
1552 arg->ref->offset); 1554 arg->ref->offset);
1553 else 1555 else
1554 ret = e_snprintf(buf, buflen, "%s", arg->value); 1556 ret = e_snprintf(buf, buflen, "%s", arg->value);
1555 if (ret < 0) 1557 if (ret < 0)
1556 return ret; 1558 return ret;
1557 buf += ret; 1559 buf += ret;
1558 buflen -= ret; 1560 buflen -= ret;
1559 1561
1560 /* Closing */ 1562 /* Closing */
1561 while (depth--) { 1563 while (depth--) {
1562 ret = e_snprintf(buf, buflen, ")"); 1564 ret = e_snprintf(buf, buflen, ")");
1563 if (ret < 0) 1565 if (ret < 0)
1564 return ret; 1566 return ret;
1565 buf += ret; 1567 buf += ret;
1566 buflen -= ret; 1568 buflen -= ret;
1567 } 1569 }
1568 /* Print argument type */ 1570 /* Print argument type */
1569 if (arg->type) { 1571 if (arg->type) {
1570 ret = e_snprintf(buf, buflen, ":%s", arg->type); 1572 ret = e_snprintf(buf, buflen, ":%s", arg->type);
1571 if (ret <= 0) 1573 if (ret <= 0)
1572 return ret; 1574 return ret;
1573 buf += ret; 1575 buf += ret;
1574 } 1576 }
1575 1577
1576 return buf - tmp; 1578 return buf - tmp;
1577 } 1579 }
1578 1580
1579 char *synthesize_probe_trace_command(struct probe_trace_event *tev) 1581 char *synthesize_probe_trace_command(struct probe_trace_event *tev)
1580 { 1582 {
1581 struct probe_trace_point *tp = &tev->point; 1583 struct probe_trace_point *tp = &tev->point;
1582 char *buf; 1584 char *buf;
1583 int i, len, ret; 1585 int i, len, ret;
1584 1586
1585 buf = zalloc(MAX_CMDLEN); 1587 buf = zalloc(MAX_CMDLEN);
1586 if (buf == NULL) 1588 if (buf == NULL)
1587 return NULL; 1589 return NULL;
1588 1590
1589 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s ", tp->retprobe ? 'r' : 'p', 1591 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
1590 tev->group, tev->event); 1592 tev->group, tev->event);
1591 if (len <= 0) 1593 if (len <= 0)
1592 goto error; 1594 goto error;
1593 1595
1594 /* Uprobes must have tp->address and tp->module */ 1596 /* Uprobes must have tp->address and tp->module */
1595 if (tev->uprobes && (!tp->address || !tp->module)) 1597 if (tev->uprobes && (!tp->address || !tp->module))
1596 goto error; 1598 goto error;
1597 1599
1598 /* Use the tp->address for uprobes */ 1600 /* Use the tp->address for uprobes */
1599 if (tev->uprobes) 1601 if (tev->uprobes)
1600 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx", 1602 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx",
1601 tp->module, tp->address); 1603 tp->module, tp->address);
1602 else 1604 else
1603 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu", 1605 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu",
1604 tp->module ?: "", tp->module ? ":" : "", 1606 tp->module ?: "", tp->module ? ":" : "",
1605 tp->symbol, tp->offset); 1607 tp->symbol, tp->offset);
1606 1608
1607 if (ret <= 0) 1609 if (ret <= 0)
1608 goto error; 1610 goto error;
1609 len += ret; 1611 len += ret;
1610 1612
1611 for (i = 0; i < tev->nargs; i++) { 1613 for (i = 0; i < tev->nargs; i++) {
1612 ret = synthesize_probe_trace_arg(&tev->args[i], buf + len, 1614 ret = synthesize_probe_trace_arg(&tev->args[i], buf + len,
1613 MAX_CMDLEN - len); 1615 MAX_CMDLEN - len);
1614 if (ret <= 0) 1616 if (ret <= 0)
1615 goto error; 1617 goto error;
1616 len += ret; 1618 len += ret;
1617 } 1619 }
1618 1620
1619 return buf; 1621 return buf;
1620 error: 1622 error:
1621 free(buf); 1623 free(buf);
1622 return NULL; 1624 return NULL;
1623 } 1625 }
1624 1626
1625 static int find_perf_probe_point_from_map(struct probe_trace_point *tp, 1627 static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
1626 struct perf_probe_point *pp, 1628 struct perf_probe_point *pp,
1627 bool is_kprobe) 1629 bool is_kprobe)
1628 { 1630 {
1629 struct symbol *sym = NULL; 1631 struct symbol *sym = NULL;
1630 struct map *map; 1632 struct map *map;
1631 u64 addr; 1633 u64 addr;
1632 int ret = -ENOENT; 1634 int ret = -ENOENT;
1633 1635
1634 if (!is_kprobe) { 1636 if (!is_kprobe) {
1635 map = dso__new_map(tp->module); 1637 map = dso__new_map(tp->module);
1636 if (!map) 1638 if (!map)
1637 goto out; 1639 goto out;
1638 addr = tp->address; 1640 addr = tp->address;
1639 sym = map__find_symbol(map, addr, NULL); 1641 sym = map__find_symbol(map, addr, NULL);
1640 } else { 1642 } else {
1641 addr = kernel_get_symbol_address_by_name(tp->symbol, true); 1643 addr = kernel_get_symbol_address_by_name(tp->symbol, true);
1642 if (addr) { 1644 if (addr) {
1643 addr += tp->offset; 1645 addr += tp->offset;
1644 sym = __find_kernel_function(addr, &map); 1646 sym = __find_kernel_function(addr, &map);
1645 } 1647 }
1646 } 1648 }
1647 if (!sym) 1649 if (!sym)
1648 goto out; 1650 goto out;
1649 1651
1650 pp->retprobe = tp->retprobe; 1652 pp->retprobe = tp->retprobe;
1651 pp->offset = addr - map->unmap_ip(map, sym->start); 1653 pp->offset = addr - map->unmap_ip(map, sym->start);
1652 pp->function = strdup(sym->name); 1654 pp->function = strdup(sym->name);
1653 ret = pp->function ? 0 : -ENOMEM; 1655 ret = pp->function ? 0 : -ENOMEM;
1654 1656
1655 out: 1657 out:
1656 if (map && !is_kprobe) { 1658 if (map && !is_kprobe) {
1657 dso__delete(map->dso); 1659 dso__delete(map->dso);
1658 map__delete(map); 1660 map__delete(map);
1659 } 1661 }
1660 1662
1661 return ret; 1663 return ret;
1662 } 1664 }
1663 1665
1664 static int convert_to_perf_probe_point(struct probe_trace_point *tp, 1666 static int convert_to_perf_probe_point(struct probe_trace_point *tp,
1665 struct perf_probe_point *pp, 1667 struct perf_probe_point *pp,
1666 bool is_kprobe) 1668 bool is_kprobe)
1667 { 1669 {
1668 char buf[128]; 1670 char buf[128];
1669 int ret; 1671 int ret;
1670 1672
1671 ret = find_perf_probe_point_from_dwarf(tp, pp, is_kprobe); 1673 ret = find_perf_probe_point_from_dwarf(tp, pp, is_kprobe);
1672 if (!ret) 1674 if (!ret)
1673 return 0; 1675 return 0;
1674 ret = find_perf_probe_point_from_map(tp, pp, is_kprobe); 1676 ret = find_perf_probe_point_from_map(tp, pp, is_kprobe);
1675 if (!ret) 1677 if (!ret)
1676 return 0; 1678 return 0;
1677 1679
1678 pr_debug("Failed to find probe point from both of dwarf and map.\n"); 1680 pr_debug("Failed to find probe point from both of dwarf and map.\n");
1679 1681
1680 if (tp->symbol) { 1682 if (tp->symbol) {
1681 pp->function = strdup(tp->symbol); 1683 pp->function = strdup(tp->symbol);
1682 pp->offset = tp->offset; 1684 pp->offset = tp->offset;
1683 } else if (!tp->module && !is_kprobe) { 1685 } else if (!tp->module && !is_kprobe) {
1684 ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address); 1686 ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address);
1685 if (ret < 0) 1687 if (ret < 0)
1686 return ret; 1688 return ret;
1687 pp->function = strdup(buf); 1689 pp->function = strdup(buf);
1688 pp->offset = 0; 1690 pp->offset = 0;
1689 } 1691 }
1690 if (pp->function == NULL) 1692 if (pp->function == NULL)
1691 return -ENOMEM; 1693 return -ENOMEM;
1692 1694
1693 pp->retprobe = tp->retprobe; 1695 pp->retprobe = tp->retprobe;
1694 1696
1695 return 0; 1697 return 0;
1696 } 1698 }
1697 1699
1698 static int convert_to_perf_probe_event(struct probe_trace_event *tev, 1700 static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1699 struct perf_probe_event *pev, bool is_kprobe) 1701 struct perf_probe_event *pev, bool is_kprobe)
1700 { 1702 {
1701 char buf[64] = ""; 1703 char buf[64] = "";
1702 int i, ret; 1704 int i, ret;
1703 1705
1704 /* Convert event/group name */ 1706 /* Convert event/group name */
1705 pev->event = strdup(tev->event); 1707 pev->event = strdup(tev->event);
1706 pev->group = strdup(tev->group); 1708 pev->group = strdup(tev->group);
1707 if (pev->event == NULL || pev->group == NULL) 1709 if (pev->event == NULL || pev->group == NULL)
1708 return -ENOMEM; 1710 return -ENOMEM;
1709 1711
1710 /* Convert trace_point to probe_point */ 1712 /* Convert trace_point to probe_point */
1711 ret = convert_to_perf_probe_point(&tev->point, &pev->point, is_kprobe); 1713 ret = convert_to_perf_probe_point(&tev->point, &pev->point, is_kprobe);
1712 if (ret < 0) 1714 if (ret < 0)
1713 return ret; 1715 return ret;
1714 1716
1715 /* Convert trace_arg to probe_arg */ 1717 /* Convert trace_arg to probe_arg */
1716 pev->nargs = tev->nargs; 1718 pev->nargs = tev->nargs;
1717 pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs); 1719 pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
1718 if (pev->args == NULL) 1720 if (pev->args == NULL)
1719 return -ENOMEM; 1721 return -ENOMEM;
1720 for (i = 0; i < tev->nargs && ret >= 0; i++) { 1722 for (i = 0; i < tev->nargs && ret >= 0; i++) {
1721 if (tev->args[i].name) 1723 if (tev->args[i].name)
1722 pev->args[i].name = strdup(tev->args[i].name); 1724 pev->args[i].name = strdup(tev->args[i].name);
1723 else { 1725 else {
1724 ret = synthesize_probe_trace_arg(&tev->args[i], 1726 ret = synthesize_probe_trace_arg(&tev->args[i],
1725 buf, 64); 1727 buf, 64);
1726 pev->args[i].name = strdup(buf); 1728 pev->args[i].name = strdup(buf);
1727 } 1729 }
1728 if (pev->args[i].name == NULL && ret >= 0) 1730 if (pev->args[i].name == NULL && ret >= 0)
1729 ret = -ENOMEM; 1731 ret = -ENOMEM;
1730 } 1732 }
1731 1733
1732 if (ret < 0) 1734 if (ret < 0)
1733 clear_perf_probe_event(pev); 1735 clear_perf_probe_event(pev);
1734 1736
1735 return ret; 1737 return ret;
1736 } 1738 }
1737 1739
1738 void clear_perf_probe_event(struct perf_probe_event *pev) 1740 void clear_perf_probe_event(struct perf_probe_event *pev)
1739 { 1741 {
1740 struct perf_probe_point *pp = &pev->point; 1742 struct perf_probe_point *pp = &pev->point;
1741 struct perf_probe_arg_field *field, *next; 1743 struct perf_probe_arg_field *field, *next;
1742 int i; 1744 int i;
1743 1745
1744 free(pev->event); 1746 free(pev->event);
1745 free(pev->group); 1747 free(pev->group);
1746 free(pp->file); 1748 free(pp->file);
1747 free(pp->function); 1749 free(pp->function);
1748 free(pp->lazy_line); 1750 free(pp->lazy_line);
1749 1751
1750 for (i = 0; i < pev->nargs; i++) { 1752 for (i = 0; i < pev->nargs; i++) {
1751 free(pev->args[i].name); 1753 free(pev->args[i].name);
1752 free(pev->args[i].var); 1754 free(pev->args[i].var);
1753 free(pev->args[i].type); 1755 free(pev->args[i].type);
1754 field = pev->args[i].field; 1756 field = pev->args[i].field;
1755 while (field) { 1757 while (field) {
1756 next = field->next; 1758 next = field->next;
1757 zfree(&field->name); 1759 zfree(&field->name);
1758 free(field); 1760 free(field);
1759 field = next; 1761 field = next;
1760 } 1762 }
1761 } 1763 }
1762 free(pev->args); 1764 free(pev->args);
1763 memset(pev, 0, sizeof(*pev)); 1765 memset(pev, 0, sizeof(*pev));
1764 } 1766 }
1765 1767
1766 static void clear_probe_trace_event(struct probe_trace_event *tev) 1768 static void clear_probe_trace_event(struct probe_trace_event *tev)
1767 { 1769 {
1768 struct probe_trace_arg_ref *ref, *next; 1770 struct probe_trace_arg_ref *ref, *next;
1769 int i; 1771 int i;
1770 1772
1771 free(tev->event); 1773 free(tev->event);
1772 free(tev->group); 1774 free(tev->group);
1773 free(tev->point.symbol); 1775 free(tev->point.symbol);
1774 free(tev->point.module); 1776 free(tev->point.module);
1775 for (i = 0; i < tev->nargs; i++) { 1777 for (i = 0; i < tev->nargs; i++) {
1776 free(tev->args[i].name); 1778 free(tev->args[i].name);
1777 free(tev->args[i].value); 1779 free(tev->args[i].value);
1778 free(tev->args[i].type); 1780 free(tev->args[i].type);
1779 ref = tev->args[i].ref; 1781 ref = tev->args[i].ref;
1780 while (ref) { 1782 while (ref) {
1781 next = ref->next; 1783 next = ref->next;
1782 free(ref); 1784 free(ref);
1783 ref = next; 1785 ref = next;
1784 } 1786 }
1785 } 1787 }
1786 free(tev->args); 1788 free(tev->args);
1787 memset(tev, 0, sizeof(*tev)); 1789 memset(tev, 0, sizeof(*tev));
1788 } 1790 }
1789 1791
1790 static void print_open_warning(int err, bool is_kprobe) 1792 static void print_open_warning(int err, bool is_kprobe)
1791 { 1793 {
1792 char sbuf[STRERR_BUFSIZE]; 1794 char sbuf[STRERR_BUFSIZE];
1793 1795
1794 if (err == -ENOENT) { 1796 if (err == -ENOENT) {
1795 const char *config; 1797 const char *config;
1796 1798
1797 if (!is_kprobe) 1799 if (!is_kprobe)
1798 config = "CONFIG_UPROBE_EVENTS"; 1800 config = "CONFIG_UPROBE_EVENTS";
1799 else 1801 else
1800 config = "CONFIG_KPROBE_EVENTS"; 1802 config = "CONFIG_KPROBE_EVENTS";
1801 1803
1802 pr_warning("%cprobe_events file does not exist" 1804 pr_warning("%cprobe_events file does not exist"
1803 " - please rebuild kernel with %s.\n", 1805 " - please rebuild kernel with %s.\n",
1804 is_kprobe ? 'k' : 'u', config); 1806 is_kprobe ? 'k' : 'u', config);
1805 } else if (err == -ENOTSUP) 1807 } else if (err == -ENOTSUP)
1806 pr_warning("Debugfs is not mounted.\n"); 1808 pr_warning("Debugfs is not mounted.\n");
1807 else 1809 else
1808 pr_warning("Failed to open %cprobe_events: %s\n", 1810 pr_warning("Failed to open %cprobe_events: %s\n",
1809 is_kprobe ? 'k' : 'u', 1811 is_kprobe ? 'k' : 'u',
1810 strerror_r(-err, sbuf, sizeof(sbuf))); 1812 strerror_r(-err, sbuf, sizeof(sbuf)));
1811 } 1813 }
1812 1814
1813 static void print_both_open_warning(int kerr, int uerr) 1815 static void print_both_open_warning(int kerr, int uerr)
1814 { 1816 {
1815 /* Both kprobes and uprobes are disabled, warn it. */ 1817 /* Both kprobes and uprobes are disabled, warn it. */
1816 if (kerr == -ENOTSUP && uerr == -ENOTSUP) 1818 if (kerr == -ENOTSUP && uerr == -ENOTSUP)
1817 pr_warning("Debugfs is not mounted.\n"); 1819 pr_warning("Debugfs is not mounted.\n");
1818 else if (kerr == -ENOENT && uerr == -ENOENT) 1820 else if (kerr == -ENOENT && uerr == -ENOENT)
1819 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS " 1821 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS "
1820 "or/and CONFIG_UPROBE_EVENTS.\n"); 1822 "or/and CONFIG_UPROBE_EVENTS.\n");
1821 else { 1823 else {
1822 char sbuf[STRERR_BUFSIZE]; 1824 char sbuf[STRERR_BUFSIZE];
1823 pr_warning("Failed to open kprobe events: %s.\n", 1825 pr_warning("Failed to open kprobe events: %s.\n",
1824 strerror_r(-kerr, sbuf, sizeof(sbuf))); 1826 strerror_r(-kerr, sbuf, sizeof(sbuf)));
1825 pr_warning("Failed to open uprobe events: %s.\n", 1827 pr_warning("Failed to open uprobe events: %s.\n",
1826 strerror_r(-uerr, sbuf, sizeof(sbuf))); 1828 strerror_r(-uerr, sbuf, sizeof(sbuf)));
1827 } 1829 }
1828 } 1830 }
1829 1831
1830 static int open_probe_events(const char *trace_file, bool readwrite) 1832 static int open_probe_events(const char *trace_file, bool readwrite)
1831 { 1833 {
1832 char buf[PATH_MAX]; 1834 char buf[PATH_MAX];
1833 const char *__debugfs; 1835 const char *__debugfs;
1834 int ret; 1836 int ret;
1835 1837
1836 __debugfs = debugfs_find_mountpoint(); 1838 __debugfs = debugfs_find_mountpoint();
1837 if (__debugfs == NULL) 1839 if (__debugfs == NULL)
1838 return -ENOTSUP; 1840 return -ENOTSUP;
1839 1841
1840 ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file); 1842 ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file);
1841 if (ret >= 0) { 1843 if (ret >= 0) {
1842 pr_debug("Opening %s write=%d\n", buf, readwrite); 1844 pr_debug("Opening %s write=%d\n", buf, readwrite);
1843 if (readwrite && !probe_event_dry_run) 1845 if (readwrite && !probe_event_dry_run)
1844 ret = open(buf, O_RDWR, O_APPEND); 1846 ret = open(buf, O_RDWR, O_APPEND);
1845 else 1847 else
1846 ret = open(buf, O_RDONLY, 0); 1848 ret = open(buf, O_RDONLY, 0);
1847 1849
1848 if (ret < 0) 1850 if (ret < 0)
1849 ret = -errno; 1851 ret = -errno;
1850 } 1852 }
1851 return ret; 1853 return ret;
1852 } 1854 }
1853 1855
1854 static int open_kprobe_events(bool readwrite) 1856 static int open_kprobe_events(bool readwrite)
1855 { 1857 {
1856 return open_probe_events("tracing/kprobe_events", readwrite); 1858 return open_probe_events("tracing/kprobe_events", readwrite);
1857 } 1859 }
1858 1860
1859 static int open_uprobe_events(bool readwrite) 1861 static int open_uprobe_events(bool readwrite)
1860 { 1862 {
1861 return open_probe_events("tracing/uprobe_events", readwrite); 1863 return open_probe_events("tracing/uprobe_events", readwrite);
1862 } 1864 }
1863 1865
1864 /* Get raw string list of current kprobe_events or uprobe_events */ 1866 /* Get raw string list of current kprobe_events or uprobe_events */
1865 static struct strlist *get_probe_trace_command_rawlist(int fd) 1867 static struct strlist *get_probe_trace_command_rawlist(int fd)
1866 { 1868 {
1867 int ret, idx; 1869 int ret, idx;
1868 FILE *fp; 1870 FILE *fp;
1869 char buf[MAX_CMDLEN]; 1871 char buf[MAX_CMDLEN];
1870 char *p; 1872 char *p;
1871 struct strlist *sl; 1873 struct strlist *sl;
1872 1874
1873 sl = strlist__new(true, NULL); 1875 sl = strlist__new(true, NULL);
1874 1876
1875 fp = fdopen(dup(fd), "r"); 1877 fp = fdopen(dup(fd), "r");
1876 while (!feof(fp)) { 1878 while (!feof(fp)) {
1877 p = fgets(buf, MAX_CMDLEN, fp); 1879 p = fgets(buf, MAX_CMDLEN, fp);
1878 if (!p) 1880 if (!p)
1879 break; 1881 break;
1880 1882
1881 idx = strlen(p) - 1; 1883 idx = strlen(p) - 1;
1882 if (p[idx] == '\n') 1884 if (p[idx] == '\n')
1883 p[idx] = '\0'; 1885 p[idx] = '\0';
1884 ret = strlist__add(sl, buf); 1886 ret = strlist__add(sl, buf);
1885 if (ret < 0) { 1887 if (ret < 0) {
1886 pr_debug("strlist__add failed (%d)\n", ret); 1888 pr_debug("strlist__add failed (%d)\n", ret);
1887 strlist__delete(sl); 1889 strlist__delete(sl);
1888 return NULL; 1890 return NULL;
1889 } 1891 }
1890 } 1892 }
1891 fclose(fp); 1893 fclose(fp);
1892 1894
1893 return sl; 1895 return sl;
1894 } 1896 }
1895 1897
1896 /* Show an event */ 1898 /* Show an event */
1897 static int show_perf_probe_event(struct perf_probe_event *pev, 1899 static int show_perf_probe_event(struct perf_probe_event *pev,
1898 const char *module) 1900 const char *module)
1899 { 1901 {
1900 int i, ret; 1902 int i, ret;
1901 char buf[128]; 1903 char buf[128];
1902 char *place; 1904 char *place;
1903 1905
1904 /* Synthesize only event probe point */ 1906 /* Synthesize only event probe point */
1905 place = synthesize_perf_probe_point(&pev->point); 1907 place = synthesize_perf_probe_point(&pev->point);
1906 if (!place) 1908 if (!place)
1907 return -EINVAL; 1909 return -EINVAL;
1908 1910
1909 ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event); 1911 ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event);
1910 if (ret < 0) 1912 if (ret < 0)
1911 return ret; 1913 return ret;
1912 1914
1913 pr_info(" %-20s (on %s", buf, place); 1915 pr_info(" %-20s (on %s", buf, place);
1914 if (module) 1916 if (module)
1915 pr_info(" in %s", module); 1917 pr_info(" in %s", module);
1916 1918
1917 if (pev->nargs > 0) { 1919 if (pev->nargs > 0) {
1918 pr_info(" with"); 1920 pr_info(" with");
1919 for (i = 0; i < pev->nargs; i++) { 1921 for (i = 0; i < pev->nargs; i++) {
1920 ret = synthesize_perf_probe_arg(&pev->args[i], 1922 ret = synthesize_perf_probe_arg(&pev->args[i],
1921 buf, 128); 1923 buf, 128);
1922 if (ret < 0) 1924 if (ret < 0)
1923 break; 1925 break;
1924 pr_info(" %s", buf); 1926 pr_info(" %s", buf);
1925 } 1927 }
1926 } 1928 }
1927 pr_info(")\n"); 1929 pr_info(")\n");
1928 free(place); 1930 free(place);
1929 return ret; 1931 return ret;
1930 } 1932 }
1931 1933
1932 static int __show_perf_probe_events(int fd, bool is_kprobe) 1934 static int __show_perf_probe_events(int fd, bool is_kprobe)
1933 { 1935 {
1934 int ret = 0; 1936 int ret = 0;
1935 struct probe_trace_event tev; 1937 struct probe_trace_event tev;
1936 struct perf_probe_event pev; 1938 struct perf_probe_event pev;
1937 struct strlist *rawlist; 1939 struct strlist *rawlist;
1938 struct str_node *ent; 1940 struct str_node *ent;
1939 1941
1940 memset(&tev, 0, sizeof(tev)); 1942 memset(&tev, 0, sizeof(tev));
1941 memset(&pev, 0, sizeof(pev)); 1943 memset(&pev, 0, sizeof(pev));
1942 1944
1943 rawlist = get_probe_trace_command_rawlist(fd); 1945 rawlist = get_probe_trace_command_rawlist(fd);
1944 if (!rawlist) 1946 if (!rawlist)
1945 return -ENOMEM; 1947 return -ENOMEM;
1946 1948
1947 strlist__for_each(ent, rawlist) { 1949 strlist__for_each(ent, rawlist) {
1948 ret = parse_probe_trace_command(ent->s, &tev); 1950 ret = parse_probe_trace_command(ent->s, &tev);
1949 if (ret >= 0) { 1951 if (ret >= 0) {
1950 ret = convert_to_perf_probe_event(&tev, &pev, 1952 ret = convert_to_perf_probe_event(&tev, &pev,
1951 is_kprobe); 1953 is_kprobe);
1952 if (ret >= 0) 1954 if (ret >= 0)
1953 ret = show_perf_probe_event(&pev, 1955 ret = show_perf_probe_event(&pev,
1954 tev.point.module); 1956 tev.point.module);
1955 } 1957 }
1956 clear_perf_probe_event(&pev); 1958 clear_perf_probe_event(&pev);
1957 clear_probe_trace_event(&tev); 1959 clear_probe_trace_event(&tev);
1958 if (ret < 0) 1960 if (ret < 0)
1959 break; 1961 break;
1960 } 1962 }
1961 strlist__delete(rawlist); 1963 strlist__delete(rawlist);
1962 1964
1963 return ret; 1965 return ret;
1964 } 1966 }
1965 1967
1966 /* List up current perf-probe events */ 1968 /* List up current perf-probe events */
1967 int show_perf_probe_events(void) 1969 int show_perf_probe_events(void)
1968 { 1970 {
1969 int kp_fd, up_fd, ret; 1971 int kp_fd, up_fd, ret;
1970 1972
1971 setup_pager(); 1973 setup_pager();
1972 1974
1973 ret = init_symbol_maps(false); 1975 ret = init_symbol_maps(false);
1974 if (ret < 0) 1976 if (ret < 0)
1975 return ret; 1977 return ret;
1976 1978
1977 kp_fd = open_kprobe_events(false); 1979 kp_fd = open_kprobe_events(false);
1978 if (kp_fd >= 0) { 1980 if (kp_fd >= 0) {
1979 ret = __show_perf_probe_events(kp_fd, true); 1981 ret = __show_perf_probe_events(kp_fd, true);
1980 close(kp_fd); 1982 close(kp_fd);
1981 if (ret < 0) 1983 if (ret < 0)
1982 goto out; 1984 goto out;
1983 } 1985 }
1984 1986
1985 up_fd = open_uprobe_events(false); 1987 up_fd = open_uprobe_events(false);
1986 if (kp_fd < 0 && up_fd < 0) { 1988 if (kp_fd < 0 && up_fd < 0) {
1987 print_both_open_warning(kp_fd, up_fd); 1989 print_both_open_warning(kp_fd, up_fd);
1988 ret = kp_fd; 1990 ret = kp_fd;
1989 goto out; 1991 goto out;
1990 } 1992 }
1991 1993
1992 if (up_fd >= 0) { 1994 if (up_fd >= 0) {
1993 ret = __show_perf_probe_events(up_fd, false); 1995 ret = __show_perf_probe_events(up_fd, false);
1994 close(up_fd); 1996 close(up_fd);
1995 } 1997 }
1996 out: 1998 out:
1997 exit_symbol_maps(); 1999 exit_symbol_maps();
1998 return ret; 2000 return ret;
1999 } 2001 }
2000 2002
2001 /* Get current perf-probe event names */ 2003 /* Get current perf-probe event names */
2002 static struct strlist *get_probe_trace_event_names(int fd, bool include_group) 2004 static struct strlist *get_probe_trace_event_names(int fd, bool include_group)
2003 { 2005 {
2004 char buf[128]; 2006 char buf[128];
2005 struct strlist *sl, *rawlist; 2007 struct strlist *sl, *rawlist;
2006 struct str_node *ent; 2008 struct str_node *ent;
2007 struct probe_trace_event tev; 2009 struct probe_trace_event tev;
2008 int ret = 0; 2010 int ret = 0;
2009 2011
2010 memset(&tev, 0, sizeof(tev)); 2012 memset(&tev, 0, sizeof(tev));
2011 rawlist = get_probe_trace_command_rawlist(fd); 2013 rawlist = get_probe_trace_command_rawlist(fd);
2012 if (!rawlist) 2014 if (!rawlist)
2013 return NULL; 2015 return NULL;
2014 sl = strlist__new(true, NULL); 2016 sl = strlist__new(true, NULL);
2015 strlist__for_each(ent, rawlist) { 2017 strlist__for_each(ent, rawlist) {
2016 ret = parse_probe_trace_command(ent->s, &tev); 2018 ret = parse_probe_trace_command(ent->s, &tev);
2017 if (ret < 0) 2019 if (ret < 0)
2018 break; 2020 break;
2019 if (include_group) { 2021 if (include_group) {
2020 ret = e_snprintf(buf, 128, "%s:%s", tev.group, 2022 ret = e_snprintf(buf, 128, "%s:%s", tev.group,
2021 tev.event); 2023 tev.event);
2022 if (ret >= 0) 2024 if (ret >= 0)
2023 ret = strlist__add(sl, buf); 2025 ret = strlist__add(sl, buf);
2024 } else 2026 } else
2025 ret = strlist__add(sl, tev.event); 2027 ret = strlist__add(sl, tev.event);
2026 clear_probe_trace_event(&tev); 2028 clear_probe_trace_event(&tev);
2027 if (ret < 0) 2029 if (ret < 0)
2028 break; 2030 break;
2029 } 2031 }
2030 strlist__delete(rawlist); 2032 strlist__delete(rawlist);
2031 2033
2032 if (ret < 0) { 2034 if (ret < 0) {
2033 strlist__delete(sl); 2035 strlist__delete(sl);
2034 return NULL; 2036 return NULL;
2035 } 2037 }
2036 return sl; 2038 return sl;
2037 } 2039 }
2038 2040
2039 static int write_probe_trace_event(int fd, struct probe_trace_event *tev) 2041 static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
2040 { 2042 {
2041 int ret = 0; 2043 int ret = 0;
2042 char *buf = synthesize_probe_trace_command(tev); 2044 char *buf = synthesize_probe_trace_command(tev);
2043 char sbuf[STRERR_BUFSIZE]; 2045 char sbuf[STRERR_BUFSIZE];
2044 2046
2045 if (!buf) { 2047 if (!buf) {
2046 pr_debug("Failed to synthesize probe trace event.\n"); 2048 pr_debug("Failed to synthesize probe trace event.\n");
2047 return -EINVAL; 2049 return -EINVAL;
2048 } 2050 }
2049 2051
2050 pr_debug("Writing event: %s\n", buf); 2052 pr_debug("Writing event: %s\n", buf);
2051 if (!probe_event_dry_run) { 2053 if (!probe_event_dry_run) {
2052 ret = write(fd, buf, strlen(buf)); 2054 ret = write(fd, buf, strlen(buf));
2053 if (ret <= 0) 2055 if (ret <= 0)
2054 pr_warning("Failed to write event: %s\n", 2056 pr_warning("Failed to write event: %s\n",
2055 strerror_r(errno, sbuf, sizeof(sbuf))); 2057 strerror_r(errno, sbuf, sizeof(sbuf)));
2056 } 2058 }
2057 free(buf); 2059 free(buf);
2058 return ret; 2060 return ret;
2059 } 2061 }
2060 2062
2061 static int get_new_event_name(char *buf, size_t len, const char *base, 2063 static int get_new_event_name(char *buf, size_t len, const char *base,
2062 struct strlist *namelist, bool allow_suffix) 2064 struct strlist *namelist, bool allow_suffix)
2063 { 2065 {
2064 int i, ret; 2066 int i, ret;
2065 2067
2066 /* Try no suffix */ 2068 /* Try no suffix */
2067 ret = e_snprintf(buf, len, "%s", base); 2069 ret = e_snprintf(buf, len, "%s", base);
2068 if (ret < 0) { 2070 if (ret < 0) {
2069 pr_debug("snprintf() failed: %d\n", ret); 2071 pr_debug("snprintf() failed: %d\n", ret);
2070 return ret; 2072 return ret;
2071 } 2073 }
2072 if (!strlist__has_entry(namelist, buf)) 2074 if (!strlist__has_entry(namelist, buf))
2073 return 0; 2075 return 0;
2074 2076
2075 if (!allow_suffix) { 2077 if (!allow_suffix) {
2076 pr_warning("Error: event \"%s\" already exists. " 2078 pr_warning("Error: event \"%s\" already exists. "
2077 "(Use -f to force duplicates.)\n", base); 2079 "(Use -f to force duplicates.)\n", base);
2078 return -EEXIST; 2080 return -EEXIST;
2079 } 2081 }
2080 2082
2081 /* Try to add suffix */ 2083 /* Try to add suffix */
2082 for (i = 1; i < MAX_EVENT_INDEX; i++) { 2084 for (i = 1; i < MAX_EVENT_INDEX; i++) {
2083 ret = e_snprintf(buf, len, "%s_%d", base, i); 2085 ret = e_snprintf(buf, len, "%s_%d", base, i);
2084 if (ret < 0) { 2086 if (ret < 0) {
2085 pr_debug("snprintf() failed: %d\n", ret); 2087 pr_debug("snprintf() failed: %d\n", ret);
2086 return ret; 2088 return ret;
2087 } 2089 }
2088 if (!strlist__has_entry(namelist, buf)) 2090 if (!strlist__has_entry(namelist, buf))
2089 break; 2091 break;
2090 } 2092 }
2091 if (i == MAX_EVENT_INDEX) { 2093 if (i == MAX_EVENT_INDEX) {
2092 pr_warning("Too many events are on the same function.\n"); 2094 pr_warning("Too many events are on the same function.\n");
2093 ret = -ERANGE; 2095 ret = -ERANGE;
2094 } 2096 }
2095 2097
2096 return ret; 2098 return ret;
2097 } 2099 }
2098 2100
2099 static int __add_probe_trace_events(struct perf_probe_event *pev, 2101 static int __add_probe_trace_events(struct perf_probe_event *pev,
2100 struct probe_trace_event *tevs, 2102 struct probe_trace_event *tevs,
2101 int ntevs, bool allow_suffix) 2103 int ntevs, bool allow_suffix)
2102 { 2104 {
2103 int i, fd, ret; 2105 int i, fd, ret;
2104 struct probe_trace_event *tev = NULL; 2106 struct probe_trace_event *tev = NULL;
2105 char buf[64]; 2107 char buf[64];
2106 const char *event, *group; 2108 const char *event, *group;
2107 struct strlist *namelist; 2109 struct strlist *namelist;
2108 2110
2109 if (pev->uprobes) 2111 if (pev->uprobes)
2110 fd = open_uprobe_events(true); 2112 fd = open_uprobe_events(true);
2111 else 2113 else
2112 fd = open_kprobe_events(true); 2114 fd = open_kprobe_events(true);
2113 2115
2114 if (fd < 0) { 2116 if (fd < 0) {
2115 print_open_warning(fd, !pev->uprobes); 2117 print_open_warning(fd, !pev->uprobes);
2116 return fd; 2118 return fd;
2117 } 2119 }
2118 2120
2119 /* Get current event names */ 2121 /* Get current event names */
2120 namelist = get_probe_trace_event_names(fd, false); 2122 namelist = get_probe_trace_event_names(fd, false);
2121 if (!namelist) { 2123 if (!namelist) {
2122 pr_debug("Failed to get current event list.\n"); 2124 pr_debug("Failed to get current event list.\n");
2123 return -EIO; 2125 return -EIO;
2124 } 2126 }
2125 2127
2126 ret = 0; 2128 ret = 0;
2127 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":"); 2129 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
2128 for (i = 0; i < ntevs; i++) { 2130 for (i = 0; i < ntevs; i++) {
2129 tev = &tevs[i]; 2131 tev = &tevs[i];
2130 if (pev->event) 2132 if (pev->event)
2131 event = pev->event; 2133 event = pev->event;
2132 else 2134 else
2133 if (pev->point.function) 2135 if (pev->point.function)
2134 event = pev->point.function; 2136 event = pev->point.function;
2135 else 2137 else
2136 event = tev->point.symbol; 2138 event = tev->point.symbol;
2137 if (pev->group) 2139 if (pev->group)
2138 group = pev->group; 2140 group = pev->group;
2139 else 2141 else
2140 group = PERFPROBE_GROUP; 2142 group = PERFPROBE_GROUP;
2141 2143
2142 /* Get an unused new event name */ 2144 /* Get an unused new event name */
2143 ret = get_new_event_name(buf, 64, event, 2145 ret = get_new_event_name(buf, 64, event,
2144 namelist, allow_suffix); 2146 namelist, allow_suffix);
2145 if (ret < 0) 2147 if (ret < 0)
2146 break; 2148 break;
2147 event = buf; 2149 event = buf;
2148 2150
2149 tev->event = strdup(event); 2151 tev->event = strdup(event);
2150 tev->group = strdup(group); 2152 tev->group = strdup(group);
2151 if (tev->event == NULL || tev->group == NULL) { 2153 if (tev->event == NULL || tev->group == NULL) {
2152 ret = -ENOMEM; 2154 ret = -ENOMEM;
2153 break; 2155 break;
2154 } 2156 }
2155 ret = write_probe_trace_event(fd, tev); 2157 ret = write_probe_trace_event(fd, tev);
2156 if (ret < 0) 2158 if (ret < 0)
2157 break; 2159 break;
2158 /* Add added event name to namelist */ 2160 /* Add added event name to namelist */
2159 strlist__add(namelist, event); 2161 strlist__add(namelist, event);
2160 2162
2161 /* Trick here - save current event/group */ 2163 /* Trick here - save current event/group */
2162 event = pev->event; 2164 event = pev->event;
2163 group = pev->group; 2165 group = pev->group;
2164 pev->event = tev->event; 2166 pev->event = tev->event;
2165 pev->group = tev->group; 2167 pev->group = tev->group;
2166 show_perf_probe_event(pev, tev->point.module); 2168 show_perf_probe_event(pev, tev->point.module);
2167 /* Trick here - restore current event/group */ 2169 /* Trick here - restore current event/group */
2168 pev->event = (char *)event; 2170 pev->event = (char *)event;
2169 pev->group = (char *)group; 2171 pev->group = (char *)group;
2170 2172
2171 /* 2173 /*
2172 * Probes after the first probe which comes from same 2174 * Probes after the first probe which comes from same
2173 * user input are always allowed to add suffix, because 2175 * user input are always allowed to add suffix, because
2174 * there might be several addresses corresponding to 2176 * there might be several addresses corresponding to
2175 * one code line. 2177 * one code line.
2176 */ 2178 */
2177 allow_suffix = true; 2179 allow_suffix = true;
2178 } 2180 }
2179 2181
2180 if (ret >= 0) { 2182 if (ret >= 0) {
2181 /* Show how to use the event. */ 2183 /* Show how to use the event. */
2182 pr_info("\nYou can now use it in all perf tools, such as:\n\n"); 2184 pr_info("\nYou can now use it in all perf tools, such as:\n\n");
2183 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 2185 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
2184 tev->event); 2186 tev->event);
2185 } 2187 }
2186 2188
2187 strlist__delete(namelist); 2189 strlist__delete(namelist);
2188 close(fd); 2190 close(fd);
2189 return ret; 2191 return ret;
2190 } 2192 }
2191 2193
2192 static char *looking_function_name; 2194 static char *looking_function_name;
2193 static int num_matched_functions; 2195 static int num_matched_functions;
2194 2196
2195 static int probe_function_filter(struct map *map __maybe_unused, 2197 static int probe_function_filter(struct map *map __maybe_unused,
2196 struct symbol *sym) 2198 struct symbol *sym)
2197 { 2199 {
2198 if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) && 2200 if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) &&
2199 strcmp(looking_function_name, sym->name) == 0) { 2201 strcmp(looking_function_name, sym->name) == 0) {
2200 num_matched_functions++; 2202 num_matched_functions++;
2201 return 0; 2203 return 0;
2202 } 2204 }
2203 return 1; 2205 return 1;
2204 } 2206 }
2205 2207
2206 #define strdup_or_goto(str, label) \ 2208 #define strdup_or_goto(str, label) \
2207 ({ char *__p = strdup(str); if (!__p) goto label; __p; }) 2209 ({ char *__p = strdup(str); if (!__p) goto label; __p; })
2208 2210
2209 /* 2211 /*
2210 * Find probe function addresses from map. 2212 * Find probe function addresses from map.
2211 * Return an error or the number of found probe_trace_event 2213 * Return an error or the number of found probe_trace_event
2212 */ 2214 */
2213 static int find_probe_trace_events_from_map(struct perf_probe_event *pev, 2215 static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2214 struct probe_trace_event **tevs, 2216 struct probe_trace_event **tevs,
2215 int max_tevs, const char *target) 2217 int max_tevs, const char *target)
2216 { 2218 {
2217 struct map *map = NULL; 2219 struct map *map = NULL;
2218 struct kmap *kmap = NULL; 2220 struct kmap *kmap = NULL;
2219 struct ref_reloc_sym *reloc_sym = NULL; 2221 struct ref_reloc_sym *reloc_sym = NULL;
2220 struct symbol *sym; 2222 struct symbol *sym;
2221 struct rb_node *nd; 2223 struct rb_node *nd;
2222 struct probe_trace_event *tev; 2224 struct probe_trace_event *tev;
2223 struct perf_probe_point *pp = &pev->point; 2225 struct perf_probe_point *pp = &pev->point;
2224 struct probe_trace_point *tp; 2226 struct probe_trace_point *tp;
2225 int ret, i; 2227 int ret, i;
2226 2228
2227 /* Init maps of given executable or kernel */ 2229 /* Init maps of given executable or kernel */
2228 if (pev->uprobes) 2230 if (pev->uprobes)
2229 map = dso__new_map(target); 2231 map = dso__new_map(target);
2230 else 2232 else
2231 map = kernel_get_module_map(target); 2233 map = kernel_get_module_map(target);
2232 if (!map) { 2234 if (!map) {
2233 ret = -EINVAL; 2235 ret = -EINVAL;
2234 goto out; 2236 goto out;
2235 } 2237 }
2236 2238
2237 /* 2239 /*
2238 * Load matched symbols: Since the different local symbols may have 2240 * Load matched symbols: Since the different local symbols may have
2239 * same name but different addresses, this lists all the symbols. 2241 * same name but different addresses, this lists all the symbols.
2240 */ 2242 */
2241 num_matched_functions = 0; 2243 num_matched_functions = 0;
2242 looking_function_name = pp->function; 2244 looking_function_name = pp->function;
2243 ret = map__load(map, probe_function_filter); 2245 ret = map__load(map, probe_function_filter);
2244 if (ret || num_matched_functions == 0) { 2246 if (ret || num_matched_functions == 0) {
2245 pr_err("Failed to find symbol %s in %s\n", pp->function, 2247 pr_err("Failed to find symbol %s in %s\n", pp->function,
2246 target ? : "kernel"); 2248 target ? : "kernel");
2247 ret = -ENOENT; 2249 ret = -ENOENT;
2248 goto out; 2250 goto out;
2249 } else if (num_matched_functions > max_tevs) { 2251 } else if (num_matched_functions > max_tevs) {
2250 pr_err("Too many functions matched in %s\n", 2252 pr_err("Too many functions matched in %s\n",
2251 target ? : "kernel"); 2253 target ? : "kernel");
2252 ret = -E2BIG; 2254 ret = -E2BIG;
2253 goto out; 2255 goto out;
2254 } 2256 }
2255 2257
2256 if (!pev->uprobes) { 2258 if (!pev->uprobes) {
2257 kmap = map__kmap(map); 2259 kmap = map__kmap(map);
2258 reloc_sym = kmap->ref_reloc_sym; 2260 reloc_sym = kmap->ref_reloc_sym;
2259 if (!reloc_sym) { 2261 if (!reloc_sym) {
2260 pr_warning("Relocated base symbol is not found!\n"); 2262 pr_warning("Relocated base symbol is not found!\n");
2261 ret = -EINVAL; 2263 ret = -EINVAL;
2262 goto out; 2264 goto out;
2263 } 2265 }
2264 } 2266 }
2265 2267
2266 /* Setup result trace-probe-events */ 2268 /* Setup result trace-probe-events */
2267 *tevs = zalloc(sizeof(*tev) * num_matched_functions); 2269 *tevs = zalloc(sizeof(*tev) * num_matched_functions);
2268 if (!*tevs) { 2270 if (!*tevs) {
2269 ret = -ENOMEM; 2271 ret = -ENOMEM;
2270 goto out; 2272 goto out;
2271 } 2273 }
2272 2274
2273 ret = 0; 2275 ret = 0;
2274 map__for_each_symbol(map, sym, nd) { 2276 map__for_each_symbol(map, sym, nd) {
2275 tev = (*tevs) + ret; 2277 tev = (*tevs) + ret;
2276 tp = &tev->point; 2278 tp = &tev->point;
2277 if (ret == num_matched_functions) { 2279 if (ret == num_matched_functions) {
2278 pr_warning("Too many symbols are listed. Skip it.\n"); 2280 pr_warning("Too many symbols are listed. Skip it.\n");
2279 break; 2281 break;
2280 } 2282 }
2281 ret++; 2283 ret++;
2282 2284
2283 if (pp->offset > sym->end - sym->start) { 2285 if (pp->offset > sym->end - sym->start) {
2284 pr_warning("Offset %ld is bigger than the size of %s\n", 2286 pr_warning("Offset %ld is bigger than the size of %s\n",
2285 pp->offset, sym->name); 2287 pp->offset, sym->name);
2286 ret = -ENOENT; 2288 ret = -ENOENT;
2287 goto err_out; 2289 goto err_out;
2288 } 2290 }
2289 /* Add one probe point */ 2291 /* Add one probe point */
2290 tp->address = map->unmap_ip(map, sym->start) + pp->offset; 2292 tp->address = map->unmap_ip(map, sym->start) + pp->offset;
2291 if (reloc_sym) { 2293 if (reloc_sym) {
2292 tp->symbol = strdup_or_goto(reloc_sym->name, nomem_out); 2294 tp->symbol = strdup_or_goto(reloc_sym->name, nomem_out);
2293 tp->offset = tp->address - reloc_sym->addr; 2295 tp->offset = tp->address - reloc_sym->addr;
2294 } else { 2296 } else {
2295 tp->symbol = strdup_or_goto(sym->name, nomem_out); 2297 tp->symbol = strdup_or_goto(sym->name, nomem_out);
2296 tp->offset = pp->offset; 2298 tp->offset = pp->offset;
2297 } 2299 }
2298 tp->retprobe = pp->retprobe; 2300 tp->retprobe = pp->retprobe;
2299 if (target) 2301 if (target)
2300 tev->point.module = strdup_or_goto(target, nomem_out); 2302 tev->point.module = strdup_or_goto(target, nomem_out);
2301 tev->uprobes = pev->uprobes; 2303 tev->uprobes = pev->uprobes;
2302 tev->nargs = pev->nargs; 2304 tev->nargs = pev->nargs;
2303 if (tev->nargs) { 2305 if (tev->nargs) {
2304 tev->args = zalloc(sizeof(struct probe_trace_arg) * 2306 tev->args = zalloc(sizeof(struct probe_trace_arg) *
2305 tev->nargs); 2307 tev->nargs);
2306 if (tev->args == NULL) 2308 if (tev->args == NULL)
2307 goto nomem_out; 2309 goto nomem_out;
2308 } 2310 }
2309 for (i = 0; i < tev->nargs; i++) { 2311 for (i = 0; i < tev->nargs; i++) {
2310 if (pev->args[i].name) 2312 if (pev->args[i].name)
2311 tev->args[i].name = 2313 tev->args[i].name =
2312 strdup_or_goto(pev->args[i].name, 2314 strdup_or_goto(pev->args[i].name,
2313 nomem_out); 2315 nomem_out);
2314 2316
2315 tev->args[i].value = strdup_or_goto(pev->args[i].var, 2317 tev->args[i].value = strdup_or_goto(pev->args[i].var,
2316 nomem_out); 2318 nomem_out);
2317 if (pev->args[i].type) 2319 if (pev->args[i].type)
2318 tev->args[i].type = 2320 tev->args[i].type =
2319 strdup_or_goto(pev->args[i].type, 2321 strdup_or_goto(pev->args[i].type,
2320 nomem_out); 2322 nomem_out);
2321 } 2323 }
2322 } 2324 }
2323 2325
2324 out: 2326 out:
2325 if (map && pev->uprobes) { 2327 if (map && pev->uprobes) {
2326 /* Only when using uprobe(exec) map needs to be released */ 2328 /* Only when using uprobe(exec) map needs to be released */
2327 dso__delete(map->dso); 2329 dso__delete(map->dso);
2328 map__delete(map); 2330 map__delete(map);
2329 } 2331 }
2330 return ret; 2332 return ret;
2331 2333
2332 nomem_out: 2334 nomem_out:
2333 ret = -ENOMEM; 2335 ret = -ENOMEM;
2334 err_out: 2336 err_out:
2335 clear_probe_trace_events(*tevs, num_matched_functions); 2337 clear_probe_trace_events(*tevs, num_matched_functions);
2336 zfree(tevs); 2338 zfree(tevs);
2337 goto out; 2339 goto out;
2338 } 2340 }
2339 2341
2340 static int convert_to_probe_trace_events(struct perf_probe_event *pev, 2342 static int convert_to_probe_trace_events(struct perf_probe_event *pev,
2341 struct probe_trace_event **tevs, 2343 struct probe_trace_event **tevs,
2342 int max_tevs, const char *target) 2344 int max_tevs, const char *target)
2343 { 2345 {
2344 int ret; 2346 int ret;
2345 2347
2346 if (pev->uprobes && !pev->group) { 2348 if (pev->uprobes && !pev->group) {
2347 /* Replace group name if not given */ 2349 /* Replace group name if not given */
2348 ret = convert_exec_to_group(target, &pev->group); 2350 ret = convert_exec_to_group(target, &pev->group);
2349 if (ret != 0) { 2351 if (ret != 0) {
2350 pr_warning("Failed to make a group name.\n"); 2352 pr_warning("Failed to make a group name.\n");
2351 return ret; 2353 return ret;
2352 } 2354 }
2353 } 2355 }
2354 2356
2355 /* Convert perf_probe_event with debuginfo */ 2357 /* Convert perf_probe_event with debuginfo */
2356 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target); 2358 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target);
2357 if (ret != 0) 2359 if (ret != 0)
2358 return ret; /* Found in debuginfo or got an error */ 2360 return ret; /* Found in debuginfo or got an error */
2359 2361
2360 return find_probe_trace_events_from_map(pev, tevs, max_tevs, target); 2362 return find_probe_trace_events_from_map(pev, tevs, max_tevs, target);
2361 } 2363 }
2362 2364
2363 struct __event_package { 2365 struct __event_package {
2364 struct perf_probe_event *pev; 2366 struct perf_probe_event *pev;
2365 struct probe_trace_event *tevs; 2367 struct probe_trace_event *tevs;
2366 int ntevs; 2368 int ntevs;
2367 }; 2369 };
2368 2370
2369 int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 2371 int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
2370 int max_tevs, const char *target, bool force_add) 2372 int max_tevs, const char *target, bool force_add)
2371 { 2373 {
2372 int i, j, ret; 2374 int i, j, ret;
2373 struct __event_package *pkgs; 2375 struct __event_package *pkgs;
2374 2376
2375 ret = 0; 2377 ret = 0;
2376 pkgs = zalloc(sizeof(struct __event_package) * npevs); 2378 pkgs = zalloc(sizeof(struct __event_package) * npevs);
2377 2379
2378 if (pkgs == NULL) 2380 if (pkgs == NULL)
2379 return -ENOMEM; 2381 return -ENOMEM;
2380 2382
2381 ret = init_symbol_maps(pevs->uprobes); 2383 ret = init_symbol_maps(pevs->uprobes);
2382 if (ret < 0) { 2384 if (ret < 0) {
2383 free(pkgs); 2385 free(pkgs);
2384 return ret; 2386 return ret;
2385 } 2387 }
2386 2388
2387 /* Loop 1: convert all events */ 2389 /* Loop 1: convert all events */
2388 for (i = 0; i < npevs; i++) { 2390 for (i = 0; i < npevs; i++) {
2389 pkgs[i].pev = &pevs[i]; 2391 pkgs[i].pev = &pevs[i];
2390 /* Convert with or without debuginfo */ 2392 /* Convert with or without debuginfo */
2391 ret = convert_to_probe_trace_events(pkgs[i].pev, 2393 ret = convert_to_probe_trace_events(pkgs[i].pev,
2392 &pkgs[i].tevs, 2394 &pkgs[i].tevs,
2393 max_tevs, 2395 max_tevs,
2394 target); 2396 target);
2395 if (ret < 0) 2397 if (ret < 0)
2396 goto end; 2398 goto end;
2397 pkgs[i].ntevs = ret; 2399 pkgs[i].ntevs = ret;
2398 } 2400 }
2399 2401
2400 /* Loop 2: add all events */ 2402 /* Loop 2: add all events */
2401 for (i = 0; i < npevs; i++) { 2403 for (i = 0; i < npevs; i++) {
2402 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs, 2404 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
2403 pkgs[i].ntevs, force_add); 2405 pkgs[i].ntevs, force_add);
2404 if (ret < 0) 2406 if (ret < 0)
2405 break; 2407 break;
2406 } 2408 }
2407 end: 2409 end:
2408 /* Loop 3: cleanup and free trace events */ 2410 /* Loop 3: cleanup and free trace events */
2409 for (i = 0; i < npevs; i++) { 2411 for (i = 0; i < npevs; i++) {
2410 for (j = 0; j < pkgs[i].ntevs; j++) 2412 for (j = 0; j < pkgs[i].ntevs; j++)
2411 clear_probe_trace_event(&pkgs[i].tevs[j]); 2413 clear_probe_trace_event(&pkgs[i].tevs[j]);
2412 zfree(&pkgs[i].tevs); 2414 zfree(&pkgs[i].tevs);
2413 } 2415 }
2414 free(pkgs); 2416 free(pkgs);
2415 exit_symbol_maps(); 2417 exit_symbol_maps();
2416 2418
2417 return ret; 2419 return ret;
2418 } 2420 }
2419 2421
2420 static int __del_trace_probe_event(int fd, struct str_node *ent) 2422 static int __del_trace_probe_event(int fd, struct str_node *ent)
2421 { 2423 {
2422 char *p; 2424 char *p;
2423 char buf[128]; 2425 char buf[128];
2424 int ret; 2426 int ret;
2425 2427
2426 /* Convert from perf-probe event to trace-probe event */ 2428 /* Convert from perf-probe event to trace-probe event */
2427 ret = e_snprintf(buf, 128, "-:%s", ent->s); 2429 ret = e_snprintf(buf, 128, "-:%s", ent->s);
2428 if (ret < 0) 2430 if (ret < 0)
2429 goto error; 2431 goto error;
2430 2432
2431 p = strchr(buf + 2, ':'); 2433 p = strchr(buf + 2, ':');
2432 if (!p) { 2434 if (!p) {
2433 pr_debug("Internal error: %s should have ':' but not.\n", 2435 pr_debug("Internal error: %s should have ':' but not.\n",
2434 ent->s); 2436 ent->s);
2435 ret = -ENOTSUP; 2437 ret = -ENOTSUP;
2436 goto error; 2438 goto error;
2437 } 2439 }
2438 *p = '/'; 2440 *p = '/';
2439 2441
2440 pr_debug("Writing event: %s\n", buf); 2442 pr_debug("Writing event: %s\n", buf);
2441 ret = write(fd, buf, strlen(buf)); 2443 ret = write(fd, buf, strlen(buf));
2442 if (ret < 0) { 2444 if (ret < 0) {
2443 ret = -errno; 2445 ret = -errno;
2444 goto error; 2446 goto error;
2445 } 2447 }
2446 2448
2447 pr_info("Removed event: %s\n", ent->s); 2449 pr_info("Removed event: %s\n", ent->s);
2448 return 0; 2450 return 0;
2449 error: 2451 error:
2450 pr_warning("Failed to delete event: %s\n", 2452 pr_warning("Failed to delete event: %s\n",
2451 strerror_r(-ret, buf, sizeof(buf))); 2453 strerror_r(-ret, buf, sizeof(buf)));
2452 return ret; 2454 return ret;
2453 } 2455 }
2454 2456
2455 static int del_trace_probe_event(int fd, const char *buf, 2457 static int del_trace_probe_event(int fd, const char *buf,
2456 struct strlist *namelist) 2458 struct strlist *namelist)
2457 { 2459 {
2458 struct str_node *ent, *n; 2460 struct str_node *ent, *n;
2459 int ret = -1; 2461 int ret = -1;
2460 2462
2461 if (strpbrk(buf, "*?")) { /* Glob-exp */ 2463 if (strpbrk(buf, "*?")) { /* Glob-exp */
2462 strlist__for_each_safe(ent, n, namelist) 2464 strlist__for_each_safe(ent, n, namelist)
2463 if (strglobmatch(ent->s, buf)) { 2465 if (strglobmatch(ent->s, buf)) {
2464 ret = __del_trace_probe_event(fd, ent); 2466 ret = __del_trace_probe_event(fd, ent);
2465 if (ret < 0) 2467 if (ret < 0)
2466 break; 2468 break;
2467 strlist__remove(namelist, ent); 2469 strlist__remove(namelist, ent);
2468 } 2470 }
2469 } else { 2471 } else {
2470 ent = strlist__find(namelist, buf); 2472 ent = strlist__find(namelist, buf);
2471 if (ent) { 2473 if (ent) {
2472 ret = __del_trace_probe_event(fd, ent); 2474 ret = __del_trace_probe_event(fd, ent);
2473 if (ret >= 0) 2475 if (ret >= 0)
2474 strlist__remove(namelist, ent); 2476 strlist__remove(namelist, ent);
2475 } 2477 }
2476 } 2478 }
2477 2479
2478 return ret; 2480 return ret;
2479 } 2481 }
2480 2482
2481 int del_perf_probe_events(struct strlist *dellist) 2483 int del_perf_probe_events(struct strlist *dellist)
2482 { 2484 {
2483 int ret = -1, ufd = -1, kfd = -1; 2485 int ret = -1, ufd = -1, kfd = -1;
2484 char buf[128]; 2486 char buf[128];
2485 const char *group, *event; 2487 const char *group, *event;
2486 char *p, *str; 2488 char *p, *str;
2487 struct str_node *ent; 2489 struct str_node *ent;
2488 struct strlist *namelist = NULL, *unamelist = NULL; 2490 struct strlist *namelist = NULL, *unamelist = NULL;
2489 2491
2490 /* Get current event names */ 2492 /* Get current event names */
2491 kfd = open_kprobe_events(true); 2493 kfd = open_kprobe_events(true);
2492 if (kfd >= 0) 2494 if (kfd >= 0)
2493 namelist = get_probe_trace_event_names(kfd, true); 2495 namelist = get_probe_trace_event_names(kfd, true);
2494 2496
2495 ufd = open_uprobe_events(true); 2497 ufd = open_uprobe_events(true);
2496 if (ufd >= 0) 2498 if (ufd >= 0)
2497 unamelist = get_probe_trace_event_names(ufd, true); 2499 unamelist = get_probe_trace_event_names(ufd, true);
2498 2500
2499 if (kfd < 0 && ufd < 0) { 2501 if (kfd < 0 && ufd < 0) {
2500 print_both_open_warning(kfd, ufd); 2502 print_both_open_warning(kfd, ufd);
2501 goto error; 2503 goto error;
2502 } 2504 }
2503 2505
2504 if (namelist == NULL && unamelist == NULL) 2506 if (namelist == NULL && unamelist == NULL)
2505 goto error; 2507 goto error;
2506 2508
2507 strlist__for_each(ent, dellist) { 2509 strlist__for_each(ent, dellist) {
2508 str = strdup(ent->s); 2510 str = strdup(ent->s);
2509 if (str == NULL) { 2511 if (str == NULL) {
2510 ret = -ENOMEM; 2512 ret = -ENOMEM;
2511 goto error; 2513 goto error;
2512 } 2514 }
2513 pr_debug("Parsing: %s\n", str); 2515 pr_debug("Parsing: %s\n", str);
2514 p = strchr(str, ':'); 2516 p = strchr(str, ':');
2515 if (p) { 2517 if (p) {
2516 group = str; 2518 group = str;
2517 *p = '\0'; 2519 *p = '\0';
2518 event = p + 1; 2520 event = p + 1;
2519 } else { 2521 } else {
2520 group = "*"; 2522 group = "*";
2521 event = str; 2523 event = str;
2522 } 2524 }
2523 2525
2524 ret = e_snprintf(buf, 128, "%s:%s", group, event); 2526 ret = e_snprintf(buf, 128, "%s:%s", group, event);
2525 if (ret < 0) { 2527 if (ret < 0) {
2526 pr_err("Failed to copy event."); 2528 pr_err("Failed to copy event.");
2527 free(str); 2529 free(str);
2528 goto error; 2530 goto error;
2529 } 2531 }
2530 2532
2531 pr_debug("Group: %s, Event: %s\n", group, event); 2533 pr_debug("Group: %s, Event: %s\n", group, event);
2532 2534
2533 if (namelist) 2535 if (namelist)
2534 ret = del_trace_probe_event(kfd, buf, namelist); 2536 ret = del_trace_probe_event(kfd, buf, namelist);
2535 2537
2536 if (unamelist && ret != 0) 2538 if (unamelist && ret != 0)
2537 ret = del_trace_probe_event(ufd, buf, unamelist); 2539 ret = del_trace_probe_event(ufd, buf, unamelist);
2538 2540
2539 if (ret != 0) 2541 if (ret != 0)
2540 pr_info("Info: Event \"%s\" does not exist.\n", buf); 2542 pr_info("Info: Event \"%s\" does not exist.\n", buf);
2541 2543
2542 free(str); 2544 free(str);
2543 } 2545 }
2544 2546
2545 error: 2547 error:
2546 if (kfd >= 0) { 2548 if (kfd >= 0) {
2547 strlist__delete(namelist); 2549 strlist__delete(namelist);
2548 close(kfd); 2550 close(kfd);
2549 } 2551 }
2550 2552
2551 if (ufd >= 0) { 2553 if (ufd >= 0) {
2552 strlist__delete(unamelist); 2554 strlist__delete(unamelist);
2553 close(ufd); 2555 close(ufd);
2554 } 2556 }
2555 2557
2556 return ret; 2558 return ret;
2557 } 2559 }
2558 2560
2559 /* TODO: don't use a global variable for filter ... */ 2561 /* TODO: don't use a global variable for filter ... */
2560 static struct strfilter *available_func_filter; 2562 static struct strfilter *available_func_filter;
2561 2563
2562 /* 2564 /*
2563 * If a symbol corresponds to a function with global binding and 2565 * If a symbol corresponds to a function with global binding and
2564 * matches filter return 0. For all others return 1. 2566 * matches filter return 0. For all others return 1.
2565 */ 2567 */
2566 static int filter_available_functions(struct map *map __maybe_unused, 2568 static int filter_available_functions(struct map *map __maybe_unused,
2567 struct symbol *sym) 2569 struct symbol *sym)
2568 { 2570 {
2569 if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) && 2571 if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) &&
2570 strfilter__compare(available_func_filter, sym->name)) 2572 strfilter__compare(available_func_filter, sym->name))
2571 return 0; 2573 return 0;
2572 return 1; 2574 return 1;
2573 } 2575 }
2574 2576
2575 int show_available_funcs(const char *target, struct strfilter *_filter, 2577 int show_available_funcs(const char *target, struct strfilter *_filter,
2576 bool user) 2578 bool user)
2577 { 2579 {
2578 struct map *map; 2580 struct map *map;
2579 int ret; 2581 int ret;
2580 2582
2581 ret = init_symbol_maps(user); 2583 ret = init_symbol_maps(user);
2582 if (ret < 0) 2584 if (ret < 0)
2583 return ret; 2585 return ret;
2584 2586
2585 /* Get a symbol map */ 2587 /* Get a symbol map */
2586 if (user) 2588 if (user)
2587 map = dso__new_map(target); 2589 map = dso__new_map(target);
2588 else 2590 else
2589 map = kernel_get_module_map(target); 2591 map = kernel_get_module_map(target);
2590 if (!map) { 2592 if (!map) {
2591 pr_err("Failed to get a map for %s\n", (target) ? : "kernel"); 2593 pr_err("Failed to get a map for %s\n", (target) ? : "kernel");
2592 return -EINVAL; 2594 return -EINVAL;
2593 } 2595 }
2594 2596
2595 /* Load symbols with given filter */ 2597 /* Load symbols with given filter */
2596 available_func_filter = _filter; 2598 available_func_filter = _filter;
2597 if (map__load(map, filter_available_functions)) { 2599 if (map__load(map, filter_available_functions)) {
2598 pr_err("Failed to load symbols in %s\n", (target) ? : "kernel"); 2600 pr_err("Failed to load symbols in %s\n", (target) ? : "kernel");
2599 goto end; 2601 goto end;
2600 } 2602 }
2601 if (!dso__sorted_by_name(map->dso, map->type)) 2603 if (!dso__sorted_by_name(map->dso, map->type))
2602 dso__sort_by_name(map->dso, map->type); 2604 dso__sort_by_name(map->dso, map->type);
2603 2605
2604 /* Show all (filtered) symbols */ 2606 /* Show all (filtered) symbols */
2605 setup_pager(); 2607 setup_pager();
2606 dso__fprintf_symbols_by_name(map->dso, map->type, stdout); 2608 dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
2607 end: 2609 end:
2608 if (user) { 2610 if (user) {
2609 dso__delete(map->dso); 2611 dso__delete(map->dso);
2610 map__delete(map); 2612 map__delete(map);
2611 } 2613 }
2612 exit_symbol_maps(); 2614 exit_symbol_maps();
2613 2615
2614 return ret; 2616 return ret;
2615 } 2617 }
2616 2618
2617 2619
tools/perf/util/probe-finder.c
1 /* 1 /*
2 * probe-finder.c : C expression to kprobe event converter 2 * probe-finder.c : C expression to kprobe event converter
3 * 3 *
4 * Written by Masami Hiramatsu <mhiramat@redhat.com> 4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or 8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version. 9 * (at your option) any later version.
10 * 10 *
11 * This program is distributed in the hope that it will be useful, 11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU General Public License 16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software 17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 * 19 *
20 */ 20 */
21 21
22 #include <sys/utsname.h> 22 #include <sys/utsname.h>
23 #include <sys/types.h> 23 #include <sys/types.h>
24 #include <sys/stat.h> 24 #include <sys/stat.h>
25 #include <fcntl.h> 25 #include <fcntl.h>
26 #include <errno.h> 26 #include <errno.h>
27 #include <stdio.h> 27 #include <stdio.h>
28 #include <unistd.h> 28 #include <unistd.h>
29 #include <stdlib.h> 29 #include <stdlib.h>
30 #include <string.h> 30 #include <string.h>
31 #include <stdarg.h> 31 #include <stdarg.h>
32 #include <dwarf-regs.h> 32 #include <dwarf-regs.h>
33 33
34 #include <linux/bitops.h> 34 #include <linux/bitops.h>
35 #include "event.h" 35 #include "event.h"
36 #include "dso.h" 36 #include "dso.h"
37 #include "debug.h" 37 #include "debug.h"
38 #include "intlist.h" 38 #include "intlist.h"
39 #include "util.h" 39 #include "util.h"
40 #include "symbol.h" 40 #include "symbol.h"
41 #include "probe-finder.h" 41 #include "probe-finder.h"
42 42
43 /* Kprobe tracer basic type is up to u64 */ 43 /* Kprobe tracer basic type is up to u64 */
44 #define MAX_BASIC_TYPE_BITS 64 44 #define MAX_BASIC_TYPE_BITS 64
45 45
46 /* Dwarf FL wrappers */ 46 /* Dwarf FL wrappers */
47 static char *debuginfo_path; /* Currently dummy */ 47 static char *debuginfo_path; /* Currently dummy */
48 48
49 static const Dwfl_Callbacks offline_callbacks = { 49 static const Dwfl_Callbacks offline_callbacks = {
50 .find_debuginfo = dwfl_standard_find_debuginfo, 50 .find_debuginfo = dwfl_standard_find_debuginfo,
51 .debuginfo_path = &debuginfo_path, 51 .debuginfo_path = &debuginfo_path,
52 52
53 .section_address = dwfl_offline_section_address, 53 .section_address = dwfl_offline_section_address,
54 54
55 /* We use this table for core files too. */ 55 /* We use this table for core files too. */
56 .find_elf = dwfl_build_id_find_elf, 56 .find_elf = dwfl_build_id_find_elf,
57 }; 57 };
58 58
59 /* Get a Dwarf from offline image */ 59 /* Get a Dwarf from offline image */
60 static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, 60 static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
61 const char *path) 61 const char *path)
62 { 62 {
63 int fd; 63 int fd;
64 64
65 fd = open(path, O_RDONLY); 65 fd = open(path, O_RDONLY);
66 if (fd < 0) 66 if (fd < 0)
67 return fd; 67 return fd;
68 68
69 dbg->dwfl = dwfl_begin(&offline_callbacks); 69 dbg->dwfl = dwfl_begin(&offline_callbacks);
70 if (!dbg->dwfl) 70 if (!dbg->dwfl)
71 goto error; 71 goto error;
72 72
73 dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd); 73 dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
74 if (!dbg->mod) 74 if (!dbg->mod)
75 goto error; 75 goto error;
76 76
77 dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias); 77 dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
78 if (!dbg->dbg) 78 if (!dbg->dbg)
79 goto error; 79 goto error;
80 80
81 return 0; 81 return 0;
82 error: 82 error:
83 if (dbg->dwfl) 83 if (dbg->dwfl)
84 dwfl_end(dbg->dwfl); 84 dwfl_end(dbg->dwfl);
85 else 85 else
86 close(fd); 86 close(fd);
87 memset(dbg, 0, sizeof(*dbg)); 87 memset(dbg, 0, sizeof(*dbg));
88 88
89 return -ENOENT; 89 return -ENOENT;
90 } 90 }
91 91
92 static struct debuginfo *__debuginfo__new(const char *path) 92 static struct debuginfo *__debuginfo__new(const char *path)
93 { 93 {
94 struct debuginfo *dbg = zalloc(sizeof(*dbg)); 94 struct debuginfo *dbg = zalloc(sizeof(*dbg));
95 if (!dbg) 95 if (!dbg)
96 return NULL; 96 return NULL;
97 97
98 if (debuginfo__init_offline_dwarf(dbg, path) < 0) 98 if (debuginfo__init_offline_dwarf(dbg, path) < 0)
99 zfree(&dbg); 99 zfree(&dbg);
100 if (dbg) 100 if (dbg)
101 pr_debug("Open Debuginfo file: %s\n", path); 101 pr_debug("Open Debuginfo file: %s\n", path);
102 return dbg; 102 return dbg;
103 } 103 }
104 104
105 enum dso_binary_type distro_dwarf_types[] = { 105 enum dso_binary_type distro_dwarf_types[] = {
106 DSO_BINARY_TYPE__FEDORA_DEBUGINFO, 106 DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
107 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO, 107 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
108 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, 108 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
109 DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 109 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
110 DSO_BINARY_TYPE__NOT_FOUND, 110 DSO_BINARY_TYPE__NOT_FOUND,
111 }; 111 };
112 112
113 struct debuginfo *debuginfo__new(const char *path) 113 struct debuginfo *debuginfo__new(const char *path)
114 { 114 {
115 enum dso_binary_type *type; 115 enum dso_binary_type *type;
116 char buf[PATH_MAX], nil = '\0'; 116 char buf[PATH_MAX], nil = '\0';
117 struct dso *dso; 117 struct dso *dso;
118 struct debuginfo *dinfo = NULL; 118 struct debuginfo *dinfo = NULL;
119 119
120 /* Try to open distro debuginfo files */ 120 /* Try to open distro debuginfo files */
121 dso = dso__new(path); 121 dso = dso__new(path);
122 if (!dso) 122 if (!dso)
123 goto out; 123 goto out;
124 124
125 for (type = distro_dwarf_types; 125 for (type = distro_dwarf_types;
126 !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND; 126 !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND;
127 type++) { 127 type++) {
128 if (dso__read_binary_type_filename(dso, *type, &nil, 128 if (dso__read_binary_type_filename(dso, *type, &nil,
129 buf, PATH_MAX) < 0) 129 buf, PATH_MAX) < 0)
130 continue; 130 continue;
131 dinfo = __debuginfo__new(buf); 131 dinfo = __debuginfo__new(buf);
132 } 132 }
133 dso__delete(dso); 133 dso__delete(dso);
134 134
135 out: 135 out:
136 /* if failed to open all distro debuginfo, open given binary */ 136 /* if failed to open all distro debuginfo, open given binary */
137 return dinfo ? : __debuginfo__new(path); 137 return dinfo ? : __debuginfo__new(path);
138 } 138 }
139 139
140 void debuginfo__delete(struct debuginfo *dbg) 140 void debuginfo__delete(struct debuginfo *dbg)
141 { 141 {
142 if (dbg) { 142 if (dbg) {
143 if (dbg->dwfl) 143 if (dbg->dwfl)
144 dwfl_end(dbg->dwfl); 144 dwfl_end(dbg->dwfl);
145 free(dbg); 145 free(dbg);
146 } 146 }
147 } 147 }
148 148
149 /* 149 /*
150 * Probe finder related functions 150 * Probe finder related functions
151 */ 151 */
152 152
153 static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs) 153 static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
154 { 154 {
155 struct probe_trace_arg_ref *ref; 155 struct probe_trace_arg_ref *ref;
156 ref = zalloc(sizeof(struct probe_trace_arg_ref)); 156 ref = zalloc(sizeof(struct probe_trace_arg_ref));
157 if (ref != NULL) 157 if (ref != NULL)
158 ref->offset = offs; 158 ref->offset = offs;
159 return ref; 159 return ref;
160 } 160 }
161 161
162 /* 162 /*
163 * Convert a location into trace_arg. 163 * Convert a location into trace_arg.
164 * If tvar == NULL, this just checks variable can be converted. 164 * If tvar == NULL, this just checks variable can be converted.
165 * If fentry == true and vr_die is a parameter, do huristic search 165 * If fentry == true and vr_die is a parameter, do huristic search
166 * for the location fuzzed by function entry mcount. 166 * for the location fuzzed by function entry mcount.
167 */ 167 */
168 static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, 168 static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
169 Dwarf_Op *fb_ops, Dwarf_Die *sp_die, 169 Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
170 struct probe_trace_arg *tvar) 170 struct probe_trace_arg *tvar)
171 { 171 {
172 Dwarf_Attribute attr; 172 Dwarf_Attribute attr;
173 Dwarf_Addr tmp = 0; 173 Dwarf_Addr tmp = 0;
174 Dwarf_Op *op; 174 Dwarf_Op *op;
175 size_t nops; 175 size_t nops;
176 unsigned int regn; 176 unsigned int regn;
177 Dwarf_Word offs = 0; 177 Dwarf_Word offs = 0;
178 bool ref = false; 178 bool ref = false;
179 const char *regs; 179 const char *regs;
180 int ret; 180 int ret;
181 181
182 if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL) 182 if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
183 goto static_var; 183 goto static_var;
184 184
185 /* TODO: handle more than 1 exprs */ 185 /* TODO: handle more than 1 exprs */
186 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL) 186 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
187 return -EINVAL; /* Broken DIE ? */ 187 return -EINVAL; /* Broken DIE ? */
188 if (dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0) { 188 if (dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0) {
189 ret = dwarf_entrypc(sp_die, &tmp); 189 ret = dwarf_entrypc(sp_die, &tmp);
190 if (ret || addr != tmp || 190 if (ret || addr != tmp ||
191 dwarf_tag(vr_die) != DW_TAG_formal_parameter || 191 dwarf_tag(vr_die) != DW_TAG_formal_parameter ||
192 dwarf_highpc(sp_die, &tmp)) 192 dwarf_highpc(sp_die, &tmp))
193 return -ENOENT; 193 return -ENOENT;
194 /* 194 /*
195 * This is fuzzed by fentry mcount. We try to find the 195 * This is fuzzed by fentry mcount. We try to find the
196 * parameter location at the earliest address. 196 * parameter location at the earliest address.
197 */ 197 */
198 for (addr += 1; addr <= tmp; addr++) { 198 for (addr += 1; addr <= tmp; addr++) {
199 if (dwarf_getlocation_addr(&attr, addr, &op, 199 if (dwarf_getlocation_addr(&attr, addr, &op,
200 &nops, 1) > 0) 200 &nops, 1) > 0)
201 goto found; 201 goto found;
202 } 202 }
203 return -ENOENT; 203 return -ENOENT;
204 } 204 }
205 found: 205 found:
206 if (nops == 0) 206 if (nops == 0)
207 /* TODO: Support const_value */ 207 /* TODO: Support const_value */
208 return -ENOENT; 208 return -ENOENT;
209 209
210 if (op->atom == DW_OP_addr) { 210 if (op->atom == DW_OP_addr) {
211 static_var: 211 static_var:
212 if (!tvar) 212 if (!tvar)
213 return 0; 213 return 0;
214 /* Static variables on memory (not stack), make @varname */ 214 /* Static variables on memory (not stack), make @varname */
215 ret = strlen(dwarf_diename(vr_die)); 215 ret = strlen(dwarf_diename(vr_die));
216 tvar->value = zalloc(ret + 2); 216 tvar->value = zalloc(ret + 2);
217 if (tvar->value == NULL) 217 if (tvar->value == NULL)
218 return -ENOMEM; 218 return -ENOMEM;
219 snprintf(tvar->value, ret + 2, "@%s", dwarf_diename(vr_die)); 219 snprintf(tvar->value, ret + 2, "@%s", dwarf_diename(vr_die));
220 tvar->ref = alloc_trace_arg_ref((long)offs); 220 tvar->ref = alloc_trace_arg_ref((long)offs);
221 if (tvar->ref == NULL) 221 if (tvar->ref == NULL)
222 return -ENOMEM; 222 return -ENOMEM;
223 return 0; 223 return 0;
224 } 224 }
225 225
226 /* If this is based on frame buffer, set the offset */ 226 /* If this is based on frame buffer, set the offset */
227 if (op->atom == DW_OP_fbreg) { 227 if (op->atom == DW_OP_fbreg) {
228 if (fb_ops == NULL) 228 if (fb_ops == NULL)
229 return -ENOTSUP; 229 return -ENOTSUP;
230 ref = true; 230 ref = true;
231 offs = op->number; 231 offs = op->number;
232 op = &fb_ops[0]; 232 op = &fb_ops[0];
233 } 233 }
234 234
235 if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) { 235 if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
236 regn = op->atom - DW_OP_breg0; 236 regn = op->atom - DW_OP_breg0;
237 offs += op->number; 237 offs += op->number;
238 ref = true; 238 ref = true;
239 } else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) { 239 } else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) {
240 regn = op->atom - DW_OP_reg0; 240 regn = op->atom - DW_OP_reg0;
241 } else if (op->atom == DW_OP_bregx) { 241 } else if (op->atom == DW_OP_bregx) {
242 regn = op->number; 242 regn = op->number;
243 offs += op->number2; 243 offs += op->number2;
244 ref = true; 244 ref = true;
245 } else if (op->atom == DW_OP_regx) { 245 } else if (op->atom == DW_OP_regx) {
246 regn = op->number; 246 regn = op->number;
247 } else { 247 } else {
248 pr_debug("DW_OP %x is not supported.\n", op->atom); 248 pr_debug("DW_OP %x is not supported.\n", op->atom);
249 return -ENOTSUP; 249 return -ENOTSUP;
250 } 250 }
251 251
252 if (!tvar) 252 if (!tvar)
253 return 0; 253 return 0;
254 254
255 regs = get_arch_regstr(regn); 255 regs = get_arch_regstr(regn);
256 if (!regs) { 256 if (!regs) {
257 /* This should be a bug in DWARF or this tool */ 257 /* This should be a bug in DWARF or this tool */
258 pr_warning("Mapping for the register number %u " 258 pr_warning("Mapping for the register number %u "
259 "missing on this architecture.\n", regn); 259 "missing on this architecture.\n", regn);
260 return -ERANGE; 260 return -ERANGE;
261 } 261 }
262 262
263 tvar->value = strdup(regs); 263 tvar->value = strdup(regs);
264 if (tvar->value == NULL) 264 if (tvar->value == NULL)
265 return -ENOMEM; 265 return -ENOMEM;
266 266
267 if (ref) { 267 if (ref) {
268 tvar->ref = alloc_trace_arg_ref((long)offs); 268 tvar->ref = alloc_trace_arg_ref((long)offs);
269 if (tvar->ref == NULL) 269 if (tvar->ref == NULL)
270 return -ENOMEM; 270 return -ENOMEM;
271 } 271 }
272 return 0; 272 return 0;
273 } 273 }
274 274
275 #define BYTES_TO_BITS(nb) ((nb) * BITS_PER_LONG / sizeof(long)) 275 #define BYTES_TO_BITS(nb) ((nb) * BITS_PER_LONG / sizeof(long))
276 276
277 static int convert_variable_type(Dwarf_Die *vr_die, 277 static int convert_variable_type(Dwarf_Die *vr_die,
278 struct probe_trace_arg *tvar, 278 struct probe_trace_arg *tvar,
279 const char *cast) 279 const char *cast)
280 { 280 {
281 struct probe_trace_arg_ref **ref_ptr = &tvar->ref; 281 struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
282 Dwarf_Die type; 282 Dwarf_Die type;
283 char buf[16]; 283 char buf[16];
284 char sbuf[STRERR_BUFSIZE]; 284 char sbuf[STRERR_BUFSIZE];
285 int bsize, boffs, total; 285 int bsize, boffs, total;
286 int ret; 286 int ret;
287 287
288 /* TODO: check all types */ 288 /* TODO: check all types */
289 if (cast && strcmp(cast, "string") != 0) { 289 if (cast && strcmp(cast, "string") != 0) {
290 /* Non string type is OK */ 290 /* Non string type is OK */
291 tvar->type = strdup(cast); 291 tvar->type = strdup(cast);
292 return (tvar->type == NULL) ? -ENOMEM : 0; 292 return (tvar->type == NULL) ? -ENOMEM : 0;
293 } 293 }
294 294
295 bsize = dwarf_bitsize(vr_die); 295 bsize = dwarf_bitsize(vr_die);
296 if (bsize > 0) { 296 if (bsize > 0) {
297 /* This is a bitfield */ 297 /* This is a bitfield */
298 boffs = dwarf_bitoffset(vr_die); 298 boffs = dwarf_bitoffset(vr_die);
299 total = dwarf_bytesize(vr_die); 299 total = dwarf_bytesize(vr_die);
300 if (boffs < 0 || total < 0) 300 if (boffs < 0 || total < 0)
301 return -ENOENT; 301 return -ENOENT;
302 ret = snprintf(buf, 16, "b%d@%d/%zd", bsize, boffs, 302 ret = snprintf(buf, 16, "b%d@%d/%zd", bsize, boffs,
303 BYTES_TO_BITS(total)); 303 BYTES_TO_BITS(total));
304 goto formatted; 304 goto formatted;
305 } 305 }
306 306
307 if (die_get_real_type(vr_die, &type) == NULL) { 307 if (die_get_real_type(vr_die, &type) == NULL) {
308 pr_warning("Failed to get a type information of %s.\n", 308 pr_warning("Failed to get a type information of %s.\n",
309 dwarf_diename(vr_die)); 309 dwarf_diename(vr_die));
310 return -ENOENT; 310 return -ENOENT;
311 } 311 }
312 312
313 pr_debug("%s type is %s.\n", 313 pr_debug("%s type is %s.\n",
314 dwarf_diename(vr_die), dwarf_diename(&type)); 314 dwarf_diename(vr_die), dwarf_diename(&type));
315 315
316 if (cast && strcmp(cast, "string") == 0) { /* String type */ 316 if (cast && strcmp(cast, "string") == 0) { /* String type */
317 ret = dwarf_tag(&type); 317 ret = dwarf_tag(&type);
318 if (ret != DW_TAG_pointer_type && 318 if (ret != DW_TAG_pointer_type &&
319 ret != DW_TAG_array_type) { 319 ret != DW_TAG_array_type) {
320 pr_warning("Failed to cast into string: " 320 pr_warning("Failed to cast into string: "
321 "%s(%s) is not a pointer nor array.\n", 321 "%s(%s) is not a pointer nor array.\n",
322 dwarf_diename(vr_die), dwarf_diename(&type)); 322 dwarf_diename(vr_die), dwarf_diename(&type));
323 return -EINVAL; 323 return -EINVAL;
324 } 324 }
325 if (die_get_real_type(&type, &type) == NULL) { 325 if (die_get_real_type(&type, &type) == NULL) {
326 pr_warning("Failed to get a type" 326 pr_warning("Failed to get a type"
327 " information.\n"); 327 " information.\n");
328 return -ENOENT; 328 return -ENOENT;
329 } 329 }
330 if (ret == DW_TAG_pointer_type) { 330 if (ret == DW_TAG_pointer_type) {
331 while (*ref_ptr) 331 while (*ref_ptr)
332 ref_ptr = &(*ref_ptr)->next; 332 ref_ptr = &(*ref_ptr)->next;
333 /* Add new reference with offset +0 */ 333 /* Add new reference with offset +0 */
334 *ref_ptr = zalloc(sizeof(struct probe_trace_arg_ref)); 334 *ref_ptr = zalloc(sizeof(struct probe_trace_arg_ref));
335 if (*ref_ptr == NULL) { 335 if (*ref_ptr == NULL) {
336 pr_warning("Out of memory error\n"); 336 pr_warning("Out of memory error\n");
337 return -ENOMEM; 337 return -ENOMEM;
338 } 338 }
339 } 339 }
340 if (!die_compare_name(&type, "char") && 340 if (!die_compare_name(&type, "char") &&
341 !die_compare_name(&type, "unsigned char")) { 341 !die_compare_name(&type, "unsigned char")) {
342 pr_warning("Failed to cast into string: " 342 pr_warning("Failed to cast into string: "
343 "%s is not (unsigned) char *.\n", 343 "%s is not (unsigned) char *.\n",
344 dwarf_diename(vr_die)); 344 dwarf_diename(vr_die));
345 return -EINVAL; 345 return -EINVAL;
346 } 346 }
347 tvar->type = strdup(cast); 347 tvar->type = strdup(cast);
348 return (tvar->type == NULL) ? -ENOMEM : 0; 348 return (tvar->type == NULL) ? -ENOMEM : 0;
349 } 349 }
350 350
351 ret = dwarf_bytesize(&type); 351 ret = dwarf_bytesize(&type);
352 if (ret <= 0) 352 if (ret <= 0)
353 /* No size ... try to use default type */ 353 /* No size ... try to use default type */
354 return 0; 354 return 0;
355 ret = BYTES_TO_BITS(ret); 355 ret = BYTES_TO_BITS(ret);
356 356
357 /* Check the bitwidth */ 357 /* Check the bitwidth */
358 if (ret > MAX_BASIC_TYPE_BITS) { 358 if (ret > MAX_BASIC_TYPE_BITS) {
359 pr_info("%s exceeds max-bitwidth. Cut down to %d bits.\n", 359 pr_info("%s exceeds max-bitwidth. Cut down to %d bits.\n",
360 dwarf_diename(&type), MAX_BASIC_TYPE_BITS); 360 dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
361 ret = MAX_BASIC_TYPE_BITS; 361 ret = MAX_BASIC_TYPE_BITS;
362 } 362 }
363 ret = snprintf(buf, 16, "%c%d", 363 ret = snprintf(buf, 16, "%c%d",
364 die_is_signed_type(&type) ? 's' : 'u', ret); 364 die_is_signed_type(&type) ? 's' : 'u', ret);
365 365
366 formatted: 366 formatted:
367 if (ret < 0 || ret >= 16) { 367 if (ret < 0 || ret >= 16) {
368 if (ret >= 16) 368 if (ret >= 16)
369 ret = -E2BIG; 369 ret = -E2BIG;
370 pr_warning("Failed to convert variable type: %s\n", 370 pr_warning("Failed to convert variable type: %s\n",
371 strerror_r(-ret, sbuf, sizeof(sbuf))); 371 strerror_r(-ret, sbuf, sizeof(sbuf)));
372 return ret; 372 return ret;
373 } 373 }
374 tvar->type = strdup(buf); 374 tvar->type = strdup(buf);
375 if (tvar->type == NULL) 375 if (tvar->type == NULL)
376 return -ENOMEM; 376 return -ENOMEM;
377 return 0; 377 return 0;
378 } 378 }
379 379
380 static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, 380 static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
381 struct perf_probe_arg_field *field, 381 struct perf_probe_arg_field *field,
382 struct probe_trace_arg_ref **ref_ptr, 382 struct probe_trace_arg_ref **ref_ptr,
383 Dwarf_Die *die_mem) 383 Dwarf_Die *die_mem)
384 { 384 {
385 struct probe_trace_arg_ref *ref = *ref_ptr; 385 struct probe_trace_arg_ref *ref = *ref_ptr;
386 Dwarf_Die type; 386 Dwarf_Die type;
387 Dwarf_Word offs; 387 Dwarf_Word offs;
388 int ret, tag; 388 int ret, tag;
389 389
390 pr_debug("converting %s in %s\n", field->name, varname); 390 pr_debug("converting %s in %s\n", field->name, varname);
391 if (die_get_real_type(vr_die, &type) == NULL) { 391 if (die_get_real_type(vr_die, &type) == NULL) {
392 pr_warning("Failed to get the type of %s.\n", varname); 392 pr_warning("Failed to get the type of %s.\n", varname);
393 return -ENOENT; 393 return -ENOENT;
394 } 394 }
395 pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type)); 395 pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type));
396 tag = dwarf_tag(&type); 396 tag = dwarf_tag(&type);
397 397
398 if (field->name[0] == '[' && 398 if (field->name[0] == '[' &&
399 (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) { 399 (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) {
400 if (field->next) 400 if (field->next)
401 /* Save original type for next field */ 401 /* Save original type for next field */
402 memcpy(die_mem, &type, sizeof(*die_mem)); 402 memcpy(die_mem, &type, sizeof(*die_mem));
403 /* Get the type of this array */ 403 /* Get the type of this array */
404 if (die_get_real_type(&type, &type) == NULL) { 404 if (die_get_real_type(&type, &type) == NULL) {
405 pr_warning("Failed to get the type of %s.\n", varname); 405 pr_warning("Failed to get the type of %s.\n", varname);
406 return -ENOENT; 406 return -ENOENT;
407 } 407 }
408 pr_debug2("Array real type: (%x)\n", 408 pr_debug2("Array real type: (%x)\n",
409 (unsigned)dwarf_dieoffset(&type)); 409 (unsigned)dwarf_dieoffset(&type));
410 if (tag == DW_TAG_pointer_type) { 410 if (tag == DW_TAG_pointer_type) {
411 ref = zalloc(sizeof(struct probe_trace_arg_ref)); 411 ref = zalloc(sizeof(struct probe_trace_arg_ref));
412 if (ref == NULL) 412 if (ref == NULL)
413 return -ENOMEM; 413 return -ENOMEM;
414 if (*ref_ptr) 414 if (*ref_ptr)
415 (*ref_ptr)->next = ref; 415 (*ref_ptr)->next = ref;
416 else 416 else
417 *ref_ptr = ref; 417 *ref_ptr = ref;
418 } 418 }
419 ref->offset += dwarf_bytesize(&type) * field->index; 419 ref->offset += dwarf_bytesize(&type) * field->index;
420 if (!field->next) 420 if (!field->next)
421 /* Save vr_die for converting types */ 421 /* Save vr_die for converting types */
422 memcpy(die_mem, vr_die, sizeof(*die_mem)); 422 memcpy(die_mem, vr_die, sizeof(*die_mem));
423 goto next; 423 goto next;
424 } else if (tag == DW_TAG_pointer_type) { 424 } else if (tag == DW_TAG_pointer_type) {
425 /* Check the pointer and dereference */ 425 /* Check the pointer and dereference */
426 if (!field->ref) { 426 if (!field->ref) {
427 pr_err("Semantic error: %s must be referred by '->'\n", 427 pr_err("Semantic error: %s must be referred by '->'\n",
428 field->name); 428 field->name);
429 return -EINVAL; 429 return -EINVAL;
430 } 430 }
431 /* Get the type pointed by this pointer */ 431 /* Get the type pointed by this pointer */
432 if (die_get_real_type(&type, &type) == NULL) { 432 if (die_get_real_type(&type, &type) == NULL) {
433 pr_warning("Failed to get the type of %s.\n", varname); 433 pr_warning("Failed to get the type of %s.\n", varname);
434 return -ENOENT; 434 return -ENOENT;
435 } 435 }
436 /* Verify it is a data structure */ 436 /* Verify it is a data structure */
437 tag = dwarf_tag(&type); 437 tag = dwarf_tag(&type);
438 if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) { 438 if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
439 pr_warning("%s is not a data structure nor an union.\n", 439 pr_warning("%s is not a data structure nor an union.\n",
440 varname); 440 varname);
441 return -EINVAL; 441 return -EINVAL;
442 } 442 }
443 443
444 ref = zalloc(sizeof(struct probe_trace_arg_ref)); 444 ref = zalloc(sizeof(struct probe_trace_arg_ref));
445 if (ref == NULL) 445 if (ref == NULL)
446 return -ENOMEM; 446 return -ENOMEM;
447 if (*ref_ptr) 447 if (*ref_ptr)
448 (*ref_ptr)->next = ref; 448 (*ref_ptr)->next = ref;
449 else 449 else
450 *ref_ptr = ref; 450 *ref_ptr = ref;
451 } else { 451 } else {
452 /* Verify it is a data structure */ 452 /* Verify it is a data structure */
453 if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) { 453 if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
454 pr_warning("%s is not a data structure nor an union.\n", 454 pr_warning("%s is not a data structure nor an union.\n",
455 varname); 455 varname);
456 return -EINVAL; 456 return -EINVAL;
457 } 457 }
458 if (field->name[0] == '[') { 458 if (field->name[0] == '[') {
459 pr_err("Semantic error: %s is not a pointor" 459 pr_err("Semantic error: %s is not a pointor"
460 " nor array.\n", varname); 460 " nor array.\n", varname);
461 return -EINVAL; 461 return -EINVAL;
462 } 462 }
463 if (field->ref) { 463 if (field->ref) {
464 pr_err("Semantic error: %s must be referred by '.'\n", 464 pr_err("Semantic error: %s must be referred by '.'\n",
465 field->name); 465 field->name);
466 return -EINVAL; 466 return -EINVAL;
467 } 467 }
468 if (!ref) { 468 if (!ref) {
469 pr_warning("Structure on a register is not " 469 pr_warning("Structure on a register is not "
470 "supported yet.\n"); 470 "supported yet.\n");
471 return -ENOTSUP; 471 return -ENOTSUP;
472 } 472 }
473 } 473 }
474 474
475 if (die_find_member(&type, field->name, die_mem) == NULL) { 475 if (die_find_member(&type, field->name, die_mem) == NULL) {
476 pr_warning("%s(type:%s) has no member %s.\n", varname, 476 pr_warning("%s(type:%s) has no member %s.\n", varname,
477 dwarf_diename(&type), field->name); 477 dwarf_diename(&type), field->name);
478 return -EINVAL; 478 return -EINVAL;
479 } 479 }
480 480
481 /* Get the offset of the field */ 481 /* Get the offset of the field */
482 if (tag == DW_TAG_union_type) { 482 if (tag == DW_TAG_union_type) {
483 offs = 0; 483 offs = 0;
484 } else { 484 } else {
485 ret = die_get_data_member_location(die_mem, &offs); 485 ret = die_get_data_member_location(die_mem, &offs);
486 if (ret < 0) { 486 if (ret < 0) {
487 pr_warning("Failed to get the offset of %s.\n", 487 pr_warning("Failed to get the offset of %s.\n",
488 field->name); 488 field->name);
489 return ret; 489 return ret;
490 } 490 }
491 } 491 }
492 ref->offset += (long)offs; 492 ref->offset += (long)offs;
493 493
494 next: 494 next:
495 /* Converting next field */ 495 /* Converting next field */
496 if (field->next) 496 if (field->next)
497 return convert_variable_fields(die_mem, field->name, 497 return convert_variable_fields(die_mem, field->name,
498 field->next, &ref, die_mem); 498 field->next, &ref, die_mem);
499 else 499 else
500 return 0; 500 return 0;
501 } 501 }
502 502
503 /* Show a variables in kprobe event format */ 503 /* Show a variables in kprobe event format */
504 static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) 504 static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
505 { 505 {
506 Dwarf_Die die_mem; 506 Dwarf_Die die_mem;
507 int ret; 507 int ret;
508 508
509 pr_debug("Converting variable %s into trace event.\n", 509 pr_debug("Converting variable %s into trace event.\n",
510 dwarf_diename(vr_die)); 510 dwarf_diename(vr_die));
511 511
512 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops, 512 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
513 &pf->sp_die, pf->tvar); 513 &pf->sp_die, pf->tvar);
514 if (ret == -ENOENT || ret == -EINVAL) 514 if (ret == -ENOENT || ret == -EINVAL)
515 pr_err("Failed to find the location of %s at this address.\n" 515 pr_err("Failed to find the location of %s at this address.\n"
516 " Perhaps, it has been optimized out.\n", pf->pvar->var); 516 " Perhaps, it has been optimized out.\n", pf->pvar->var);
517 else if (ret == -ENOTSUP) 517 else if (ret == -ENOTSUP)
518 pr_err("Sorry, we don't support this variable location yet.\n"); 518 pr_err("Sorry, we don't support this variable location yet.\n");
519 else if (ret == 0 && pf->pvar->field) { 519 else if (ret == 0 && pf->pvar->field) {
520 ret = convert_variable_fields(vr_die, pf->pvar->var, 520 ret = convert_variable_fields(vr_die, pf->pvar->var,
521 pf->pvar->field, &pf->tvar->ref, 521 pf->pvar->field, &pf->tvar->ref,
522 &die_mem); 522 &die_mem);
523 vr_die = &die_mem; 523 vr_die = &die_mem;
524 } 524 }
525 if (ret == 0) 525 if (ret == 0)
526 ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type); 526 ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
527 /* *expr will be cached in libdw. Don't free it. */ 527 /* *expr will be cached in libdw. Don't free it. */
528 return ret; 528 return ret;
529 } 529 }
530 530
531 /* Find a variable in a scope DIE */ 531 /* Find a variable in a scope DIE */
532 static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) 532 static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
533 { 533 {
534 Dwarf_Die vr_die; 534 Dwarf_Die vr_die;
535 char buf[32], *ptr; 535 char buf[32], *ptr;
536 int ret = 0; 536 int ret = 0;
537 537
538 if (!is_c_varname(pf->pvar->var)) { 538 if (!is_c_varname(pf->pvar->var)) {
539 /* Copy raw parameters */ 539 /* Copy raw parameters */
540 pf->tvar->value = strdup(pf->pvar->var); 540 pf->tvar->value = strdup(pf->pvar->var);
541 if (pf->tvar->value == NULL) 541 if (pf->tvar->value == NULL)
542 return -ENOMEM; 542 return -ENOMEM;
543 if (pf->pvar->type) { 543 if (pf->pvar->type) {
544 pf->tvar->type = strdup(pf->pvar->type); 544 pf->tvar->type = strdup(pf->pvar->type);
545 if (pf->tvar->type == NULL) 545 if (pf->tvar->type == NULL)
546 return -ENOMEM; 546 return -ENOMEM;
547 } 547 }
548 if (pf->pvar->name) { 548 if (pf->pvar->name) {
549 pf->tvar->name = strdup(pf->pvar->name); 549 pf->tvar->name = strdup(pf->pvar->name);
550 if (pf->tvar->name == NULL) 550 if (pf->tvar->name == NULL)
551 return -ENOMEM; 551 return -ENOMEM;
552 } else 552 } else
553 pf->tvar->name = NULL; 553 pf->tvar->name = NULL;
554 return 0; 554 return 0;
555 } 555 }
556 556
557 if (pf->pvar->name) 557 if (pf->pvar->name)
558 pf->tvar->name = strdup(pf->pvar->name); 558 pf->tvar->name = strdup(pf->pvar->name);
559 else { 559 else {
560 ret = synthesize_perf_probe_arg(pf->pvar, buf, 32); 560 ret = synthesize_perf_probe_arg(pf->pvar, buf, 32);
561 if (ret < 0) 561 if (ret < 0)
562 return ret; 562 return ret;
563 ptr = strchr(buf, ':'); /* Change type separator to _ */ 563 ptr = strchr(buf, ':'); /* Change type separator to _ */
564 if (ptr) 564 if (ptr)
565 *ptr = '_'; 565 *ptr = '_';
566 pf->tvar->name = strdup(buf); 566 pf->tvar->name = strdup(buf);
567 } 567 }
568 if (pf->tvar->name == NULL) 568 if (pf->tvar->name == NULL)
569 return -ENOMEM; 569 return -ENOMEM;
570 570
571 pr_debug("Searching '%s' variable in context.\n", pf->pvar->var); 571 pr_debug("Searching '%s' variable in context.\n", pf->pvar->var);
572 /* Search child die for local variables and parameters. */ 572 /* Search child die for local variables and parameters. */
573 if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) { 573 if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) {
574 /* Search again in global variables */ 574 /* Search again in global variables */
575 if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, 0, &vr_die)) 575 if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, 0, &vr_die))
576 pr_warning("Failed to find '%s' in this function.\n", 576 pr_warning("Failed to find '%s' in this function.\n",
577 pf->pvar->var); 577 pf->pvar->var);
578 ret = -ENOENT; 578 ret = -ENOENT;
579 } 579 }
580 if (ret >= 0) 580 if (ret >= 0)
581 ret = convert_variable(&vr_die, pf); 581 ret = convert_variable(&vr_die, pf);
582 582
583 return ret; 583 return ret;
584 } 584 }
585 585
586 /* Convert subprogram DIE to trace point */ 586 /* Convert subprogram DIE to trace point */
587 static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, 587 static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
588 Dwarf_Addr paddr, bool retprobe, 588 Dwarf_Addr paddr, bool retprobe,
589 struct probe_trace_point *tp) 589 struct probe_trace_point *tp)
590 { 590 {
591 Dwarf_Addr eaddr, highaddr; 591 Dwarf_Addr eaddr, highaddr;
592 GElf_Sym sym; 592 GElf_Sym sym;
593 const char *symbol; 593 const char *symbol;
594 594
595 /* Verify the address is correct */ 595 /* Verify the address is correct */
596 if (dwarf_entrypc(sp_die, &eaddr) != 0) { 596 if (dwarf_entrypc(sp_die, &eaddr) != 0) {
597 pr_warning("Failed to get entry address of %s\n", 597 pr_warning("Failed to get entry address of %s\n",
598 dwarf_diename(sp_die)); 598 dwarf_diename(sp_die));
599 return -ENOENT; 599 return -ENOENT;
600 } 600 }
601 if (dwarf_highpc(sp_die, &highaddr) != 0) { 601 if (dwarf_highpc(sp_die, &highaddr) != 0) {
602 pr_warning("Failed to get end address of %s\n", 602 pr_warning("Failed to get end address of %s\n",
603 dwarf_diename(sp_die)); 603 dwarf_diename(sp_die));
604 return -ENOENT; 604 return -ENOENT;
605 } 605 }
606 if (paddr > highaddr) { 606 if (paddr > highaddr) {
607 pr_warning("Offset specified is greater than size of %s\n", 607 pr_warning("Offset specified is greater than size of %s\n",
608 dwarf_diename(sp_die)); 608 dwarf_diename(sp_die));
609 return -EINVAL; 609 return -EINVAL;
610 } 610 }
611 611
612 symbol = dwarf_diename(sp_die); 612 symbol = dwarf_diename(sp_die);
613 if (!symbol) { 613 if (!symbol) {
614 /* Try to get the symbol name from symtab */ 614 /* Try to get the symbol name from symtab */
615 symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL); 615 symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
616 if (!symbol) { 616 if (!symbol) {
617 pr_warning("Failed to find symbol at 0x%lx\n", 617 pr_warning("Failed to find symbol at 0x%lx\n",
618 (unsigned long)paddr); 618 (unsigned long)paddr);
619 return -ENOENT; 619 return -ENOENT;
620 } 620 }
621 eaddr = sym.st_value; 621 eaddr = sym.st_value;
622 } 622 }
623 tp->offset = (unsigned long)(paddr - eaddr); 623 tp->offset = (unsigned long)(paddr - eaddr);
624 tp->address = (unsigned long)paddr; 624 tp->address = (unsigned long)paddr;
625 tp->symbol = strdup(symbol); 625 tp->symbol = strdup(symbol);
626 if (!tp->symbol) 626 if (!tp->symbol)
627 return -ENOMEM; 627 return -ENOMEM;
628 628
629 /* Return probe must be on the head of a subprogram */ 629 /* Return probe must be on the head of a subprogram */
630 if (retprobe) { 630 if (retprobe) {
631 if (eaddr != paddr) { 631 if (eaddr != paddr) {
632 pr_warning("Return probe must be on the head of" 632 pr_warning("Return probe must be on the head of"
633 " a real function.\n"); 633 " a real function.\n");
634 return -EINVAL; 634 return -EINVAL;
635 } 635 }
636 tp->retprobe = true; 636 tp->retprobe = true;
637 } 637 }
638 638
639 return 0; 639 return 0;
640 } 640 }
641 641
642 /* Call probe_finder callback with scope DIE */ 642 /* Call probe_finder callback with scope DIE */
643 static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf) 643 static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
644 { 644 {
645 Dwarf_Attribute fb_attr; 645 Dwarf_Attribute fb_attr;
646 size_t nops; 646 size_t nops;
647 int ret; 647 int ret;
648 648
649 if (!sc_die) { 649 if (!sc_die) {
650 pr_err("Caller must pass a scope DIE. Program error.\n"); 650 pr_err("Caller must pass a scope DIE. Program error.\n");
651 return -EINVAL; 651 return -EINVAL;
652 } 652 }
653 653
654 /* If not a real subprogram, find a real one */ 654 /* If not a real subprogram, find a real one */
655 if (!die_is_func_def(sc_die)) { 655 if (!die_is_func_def(sc_die)) {
656 if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) { 656 if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
657 pr_warning("Failed to find probe point in any " 657 pr_warning("Failed to find probe point in any "
658 "functions.\n"); 658 "functions.\n");
659 return -ENOENT; 659 return -ENOENT;
660 } 660 }
661 } else 661 } else
662 memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die)); 662 memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die));
663 663
664 /* Get the frame base attribute/ops from subprogram */ 664 /* Get the frame base attribute/ops from subprogram */
665 dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr); 665 dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr);
666 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1); 666 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
667 if (ret <= 0 || nops == 0) { 667 if (ret <= 0 || nops == 0) {
668 pf->fb_ops = NULL; 668 pf->fb_ops = NULL;
669 #if _ELFUTILS_PREREQ(0, 142) 669 #if _ELFUTILS_PREREQ(0, 142)
670 } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa && 670 } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
671 pf->cfi != NULL) { 671 pf->cfi != NULL) {
672 Dwarf_Frame *frame; 672 Dwarf_Frame *frame;
673 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 || 673 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
674 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) { 674 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
675 pr_warning("Failed to get call frame on 0x%jx\n", 675 pr_warning("Failed to get call frame on 0x%jx\n",
676 (uintmax_t)pf->addr); 676 (uintmax_t)pf->addr);
677 return -ENOENT; 677 return -ENOENT;
678 } 678 }
679 #endif 679 #endif
680 } 680 }
681 681
682 /* Call finder's callback handler */ 682 /* Call finder's callback handler */
683 ret = pf->callback(sc_die, pf); 683 ret = pf->callback(sc_die, pf);
684 684
685 /* *pf->fb_ops will be cached in libdw. Don't free it. */ 685 /* *pf->fb_ops will be cached in libdw. Don't free it. */
686 pf->fb_ops = NULL; 686 pf->fb_ops = NULL;
687 687
688 return ret; 688 return ret;
689 } 689 }
690 690
691 struct find_scope_param { 691 struct find_scope_param {
692 const char *function; 692 const char *function;
693 const char *file; 693 const char *file;
694 int line; 694 int line;
695 int diff; 695 int diff;
696 Dwarf_Die *die_mem; 696 Dwarf_Die *die_mem;
697 bool found; 697 bool found;
698 }; 698 };
699 699
700 static int find_best_scope_cb(Dwarf_Die *fn_die, void *data) 700 static int find_best_scope_cb(Dwarf_Die *fn_die, void *data)
701 { 701 {
702 struct find_scope_param *fsp = data; 702 struct find_scope_param *fsp = data;
703 const char *file; 703 const char *file;
704 int lno; 704 int lno;
705 705
706 /* Skip if declared file name does not match */ 706 /* Skip if declared file name does not match */
707 if (fsp->file) { 707 if (fsp->file) {
708 file = dwarf_decl_file(fn_die); 708 file = dwarf_decl_file(fn_die);
709 if (!file || strcmp(fsp->file, file) != 0) 709 if (!file || strcmp(fsp->file, file) != 0)
710 return 0; 710 return 0;
711 } 711 }
712 /* If the function name is given, that's what user expects */ 712 /* If the function name is given, that's what user expects */
713 if (fsp->function) { 713 if (fsp->function) {
714 if (die_compare_name(fn_die, fsp->function)) { 714 if (die_compare_name(fn_die, fsp->function)) {
715 memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die)); 715 memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
716 fsp->found = true; 716 fsp->found = true;
717 return 1; 717 return 1;
718 } 718 }
719 } else { 719 } else {
720 /* With the line number, find the nearest declared DIE */ 720 /* With the line number, find the nearest declared DIE */
721 dwarf_decl_line(fn_die, &lno); 721 dwarf_decl_line(fn_die, &lno);
722 if (lno < fsp->line && fsp->diff > fsp->line - lno) { 722 if (lno < fsp->line && fsp->diff > fsp->line - lno) {
723 /* Keep a candidate and continue */ 723 /* Keep a candidate and continue */
724 fsp->diff = fsp->line - lno; 724 fsp->diff = fsp->line - lno;
725 memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die)); 725 memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
726 fsp->found = true; 726 fsp->found = true;
727 } 727 }
728 } 728 }
729 return 0; 729 return 0;
730 } 730 }
731 731
732 /* Find an appropriate scope fits to given conditions */ 732 /* Find an appropriate scope fits to given conditions */
733 static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem) 733 static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem)
734 { 734 {
735 struct find_scope_param fsp = { 735 struct find_scope_param fsp = {
736 .function = pf->pev->point.function, 736 .function = pf->pev->point.function,
737 .file = pf->fname, 737 .file = pf->fname,
738 .line = pf->lno, 738 .line = pf->lno,
739 .diff = INT_MAX, 739 .diff = INT_MAX,
740 .die_mem = die_mem, 740 .die_mem = die_mem,
741 .found = false, 741 .found = false,
742 }; 742 };
743 743
744 cu_walk_functions_at(&pf->cu_die, pf->addr, find_best_scope_cb, &fsp); 744 cu_walk_functions_at(&pf->cu_die, pf->addr, find_best_scope_cb, &fsp);
745 745
746 return fsp.found ? die_mem : NULL; 746 return fsp.found ? die_mem : NULL;
747 } 747 }
748 748
749 static int probe_point_line_walker(const char *fname, int lineno, 749 static int probe_point_line_walker(const char *fname, int lineno,
750 Dwarf_Addr addr, void *data) 750 Dwarf_Addr addr, void *data)
751 { 751 {
752 struct probe_finder *pf = data; 752 struct probe_finder *pf = data;
753 Dwarf_Die *sc_die, die_mem; 753 Dwarf_Die *sc_die, die_mem;
754 int ret; 754 int ret;
755 755
756 if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0) 756 if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0)
757 return 0; 757 return 0;
758 758
759 pf->addr = addr; 759 pf->addr = addr;
760 sc_die = find_best_scope(pf, &die_mem); 760 sc_die = find_best_scope(pf, &die_mem);
761 if (!sc_die) { 761 if (!sc_die) {
762 pr_warning("Failed to find scope of probe point.\n"); 762 pr_warning("Failed to find scope of probe point.\n");
763 return -ENOENT; 763 return -ENOENT;
764 } 764 }
765 765
766 ret = call_probe_finder(sc_die, pf); 766 ret = call_probe_finder(sc_die, pf);
767 767
768 /* Continue if no error, because the line will be in inline function */ 768 /* Continue if no error, because the line will be in inline function */
769 return ret < 0 ? ret : 0; 769 return ret < 0 ? ret : 0;
770 } 770 }
771 771
772 /* Find probe point from its line number */ 772 /* Find probe point from its line number */
773 static int find_probe_point_by_line(struct probe_finder *pf) 773 static int find_probe_point_by_line(struct probe_finder *pf)
774 { 774 {
775 return die_walk_lines(&pf->cu_die, probe_point_line_walker, pf); 775 return die_walk_lines(&pf->cu_die, probe_point_line_walker, pf);
776 } 776 }
777 777
778 /* Find lines which match lazy pattern */ 778 /* Find lines which match lazy pattern */
779 static int find_lazy_match_lines(struct intlist *list, 779 static int find_lazy_match_lines(struct intlist *list,
780 const char *fname, const char *pat) 780 const char *fname, const char *pat)
781 { 781 {
782 FILE *fp; 782 FILE *fp;
783 char *line = NULL; 783 char *line = NULL;
784 size_t line_len; 784 size_t line_len;
785 ssize_t len; 785 ssize_t len;
786 int count = 0, linenum = 1; 786 int count = 0, linenum = 1;
787 char sbuf[STRERR_BUFSIZE]; 787 char sbuf[STRERR_BUFSIZE];
788 788
789 fp = fopen(fname, "r"); 789 fp = fopen(fname, "r");
790 if (!fp) { 790 if (!fp) {
791 pr_warning("Failed to open %s: %s\n", fname, 791 pr_warning("Failed to open %s: %s\n", fname,
792 strerror_r(errno, sbuf, sizeof(sbuf))); 792 strerror_r(errno, sbuf, sizeof(sbuf)));
793 return -errno; 793 return -errno;
794 } 794 }
795 795
796 while ((len = getline(&line, &line_len, fp)) > 0) { 796 while ((len = getline(&line, &line_len, fp)) > 0) {
797 797
798 if (line[len - 1] == '\n') 798 if (line[len - 1] == '\n')
799 line[len - 1] = '\0'; 799 line[len - 1] = '\0';
800 800
801 if (strlazymatch(line, pat)) { 801 if (strlazymatch(line, pat)) {
802 intlist__add(list, linenum); 802 intlist__add(list, linenum);
803 count++; 803 count++;
804 } 804 }
805 linenum++; 805 linenum++;
806 } 806 }
807 807
808 if (ferror(fp)) 808 if (ferror(fp))
809 count = -errno; 809 count = -errno;
810 free(line); 810 free(line);
811 fclose(fp); 811 fclose(fp);
812 812
813 if (count == 0) 813 if (count == 0)
814 pr_debug("No matched lines found in %s.\n", fname); 814 pr_debug("No matched lines found in %s.\n", fname);
815 return count; 815 return count;
816 } 816 }
817 817
818 static int probe_point_lazy_walker(const char *fname, int lineno, 818 static int probe_point_lazy_walker(const char *fname, int lineno,
819 Dwarf_Addr addr, void *data) 819 Dwarf_Addr addr, void *data)
820 { 820 {
821 struct probe_finder *pf = data; 821 struct probe_finder *pf = data;
822 Dwarf_Die *sc_die, die_mem; 822 Dwarf_Die *sc_die, die_mem;
823 int ret; 823 int ret;
824 824
825 if (!intlist__has_entry(pf->lcache, lineno) || 825 if (!intlist__has_entry(pf->lcache, lineno) ||
826 strtailcmp(fname, pf->fname) != 0) 826 strtailcmp(fname, pf->fname) != 0)
827 return 0; 827 return 0;
828 828
829 pr_debug("Probe line found: line:%d addr:0x%llx\n", 829 pr_debug("Probe line found: line:%d addr:0x%llx\n",
830 lineno, (unsigned long long)addr); 830 lineno, (unsigned long long)addr);
831 pf->addr = addr; 831 pf->addr = addr;
832 pf->lno = lineno; 832 pf->lno = lineno;
833 sc_die = find_best_scope(pf, &die_mem); 833 sc_die = find_best_scope(pf, &die_mem);
834 if (!sc_die) { 834 if (!sc_die) {
835 pr_warning("Failed to find scope of probe point.\n"); 835 pr_warning("Failed to find scope of probe point.\n");
836 return -ENOENT; 836 return -ENOENT;
837 } 837 }
838 838
839 ret = call_probe_finder(sc_die, pf); 839 ret = call_probe_finder(sc_die, pf);
840 840
841 /* 841 /*
842 * Continue if no error, because the lazy pattern will match 842 * Continue if no error, because the lazy pattern will match
843 * to other lines 843 * to other lines
844 */ 844 */
845 return ret < 0 ? ret : 0; 845 return ret < 0 ? ret : 0;
846 } 846 }
847 847
848 /* Find probe points from lazy pattern */ 848 /* Find probe points from lazy pattern */
849 static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) 849 static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
850 { 850 {
851 int ret = 0; 851 int ret = 0;
852 852
853 if (intlist__empty(pf->lcache)) { 853 if (intlist__empty(pf->lcache)) {
854 /* Matching lazy line pattern */ 854 /* Matching lazy line pattern */
855 ret = find_lazy_match_lines(pf->lcache, pf->fname, 855 ret = find_lazy_match_lines(pf->lcache, pf->fname,
856 pf->pev->point.lazy_line); 856 pf->pev->point.lazy_line);
857 if (ret <= 0) 857 if (ret <= 0)
858 return ret; 858 return ret;
859 } 859 }
860 860
861 return die_walk_lines(sp_die, probe_point_lazy_walker, pf); 861 return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
862 } 862 }
863 863
864 static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) 864 static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
865 { 865 {
866 struct probe_finder *pf = data; 866 struct probe_finder *pf = data;
867 struct perf_probe_point *pp = &pf->pev->point; 867 struct perf_probe_point *pp = &pf->pev->point;
868 Dwarf_Addr addr; 868 Dwarf_Addr addr;
869 int ret; 869 int ret;
870 870
871 if (pp->lazy_line) 871 if (pp->lazy_line)
872 ret = find_probe_point_lazy(in_die, pf); 872 ret = find_probe_point_lazy(in_die, pf);
873 else { 873 else {
874 /* Get probe address */ 874 /* Get probe address */
875 if (dwarf_entrypc(in_die, &addr) != 0) { 875 if (dwarf_entrypc(in_die, &addr) != 0) {
876 pr_warning("Failed to get entry address of %s.\n", 876 pr_warning("Failed to get entry address of %s.\n",
877 dwarf_diename(in_die)); 877 dwarf_diename(in_die));
878 return -ENOENT; 878 return -ENOENT;
879 } 879 }
880 pf->addr = addr; 880 pf->addr = addr;
881 pf->addr += pp->offset; 881 pf->addr += pp->offset;
882 pr_debug("found inline addr: 0x%jx\n", 882 pr_debug("found inline addr: 0x%jx\n",
883 (uintmax_t)pf->addr); 883 (uintmax_t)pf->addr);
884 884
885 ret = call_probe_finder(in_die, pf); 885 ret = call_probe_finder(in_die, pf);
886 } 886 }
887 887
888 return ret; 888 return ret;
889 } 889 }
890 890
891 /* Callback parameter with return value for libdw */ 891 /* Callback parameter with return value for libdw */
892 struct dwarf_callback_param { 892 struct dwarf_callback_param {
893 void *data; 893 void *data;
894 int retval; 894 int retval;
895 }; 895 };
896 896
897 /* Search function from function name */ 897 /* Search function from function name */
898 static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) 898 static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
899 { 899 {
900 struct dwarf_callback_param *param = data; 900 struct dwarf_callback_param *param = data;
901 struct probe_finder *pf = param->data; 901 struct probe_finder *pf = param->data;
902 struct perf_probe_point *pp = &pf->pev->point; 902 struct perf_probe_point *pp = &pf->pev->point;
903 903
904 /* Check tag and diename */ 904 /* Check tag and diename */
905 if (!die_is_func_def(sp_die) || 905 if (!die_is_func_def(sp_die) ||
906 !die_compare_name(sp_die, pp->function)) 906 !die_compare_name(sp_die, pp->function))
907 return DWARF_CB_OK; 907 return DWARF_CB_OK;
908 908
909 /* Check declared file */ 909 /* Check declared file */
910 if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die))) 910 if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
911 return DWARF_CB_OK; 911 return DWARF_CB_OK;
912 912
913 pf->fname = dwarf_decl_file(sp_die); 913 pf->fname = dwarf_decl_file(sp_die);
914 if (pp->line) { /* Function relative line */ 914 if (pp->line) { /* Function relative line */
915 dwarf_decl_line(sp_die, &pf->lno); 915 dwarf_decl_line(sp_die, &pf->lno);
916 pf->lno += pp->line; 916 pf->lno += pp->line;
917 param->retval = find_probe_point_by_line(pf); 917 param->retval = find_probe_point_by_line(pf);
918 } else if (!dwarf_func_inline(sp_die)) { 918 } else if (!dwarf_func_inline(sp_die)) {
919 /* Real function */ 919 /* Real function */
920 if (pp->lazy_line) 920 if (pp->lazy_line)
921 param->retval = find_probe_point_lazy(sp_die, pf); 921 param->retval = find_probe_point_lazy(sp_die, pf);
922 else { 922 else {
923 if (dwarf_entrypc(sp_die, &pf->addr) != 0) { 923 if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
924 pr_warning("Failed to get entry address of " 924 pr_warning("Failed to get entry address of "
925 "%s.\n", dwarf_diename(sp_die)); 925 "%s.\n", dwarf_diename(sp_die));
926 param->retval = -ENOENT; 926 param->retval = -ENOENT;
927 return DWARF_CB_ABORT; 927 return DWARF_CB_ABORT;
928 } 928 }
929 pf->addr += pp->offset; 929 pf->addr += pp->offset;
930 /* TODO: Check the address in this function */ 930 /* TODO: Check the address in this function */
931 param->retval = call_probe_finder(sp_die, pf); 931 param->retval = call_probe_finder(sp_die, pf);
932 } 932 }
933 } else 933 } else
934 /* Inlined function: search instances */ 934 /* Inlined function: search instances */
935 param->retval = die_walk_instances(sp_die, 935 param->retval = die_walk_instances(sp_die,
936 probe_point_inline_cb, (void *)pf); 936 probe_point_inline_cb, (void *)pf);
937 937
938 return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */ 938 return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
939 } 939 }
940 940
941 static int find_probe_point_by_func(struct probe_finder *pf) 941 static int find_probe_point_by_func(struct probe_finder *pf)
942 { 942 {
943 struct dwarf_callback_param _param = {.data = (void *)pf, 943 struct dwarf_callback_param _param = {.data = (void *)pf,
944 .retval = 0}; 944 .retval = 0};
945 dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0); 945 dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
946 return _param.retval; 946 return _param.retval;
947 } 947 }
948 948
949 struct pubname_callback_param { 949 struct pubname_callback_param {
950 char *function; 950 char *function;
951 char *file; 951 char *file;
952 Dwarf_Die *cu_die; 952 Dwarf_Die *cu_die;
953 Dwarf_Die *sp_die; 953 Dwarf_Die *sp_die;
954 int found; 954 int found;
955 }; 955 };
956 956
957 static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data) 957 static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
958 { 958 {
959 struct pubname_callback_param *param = data; 959 struct pubname_callback_param *param = data;
960 960
961 if (dwarf_offdie(dbg, gl->die_offset, param->sp_die)) { 961 if (dwarf_offdie(dbg, gl->die_offset, param->sp_die)) {
962 if (dwarf_tag(param->sp_die) != DW_TAG_subprogram) 962 if (dwarf_tag(param->sp_die) != DW_TAG_subprogram)
963 return DWARF_CB_OK; 963 return DWARF_CB_OK;
964 964
965 if (die_compare_name(param->sp_die, param->function)) { 965 if (die_compare_name(param->sp_die, param->function)) {
966 if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die)) 966 if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die))
967 return DWARF_CB_OK; 967 return DWARF_CB_OK;
968 968
969 if (param->file && 969 if (param->file &&
970 strtailcmp(param->file, dwarf_decl_file(param->sp_die))) 970 strtailcmp(param->file, dwarf_decl_file(param->sp_die)))
971 return DWARF_CB_OK; 971 return DWARF_CB_OK;
972 972
973 param->found = 1; 973 param->found = 1;
974 return DWARF_CB_ABORT; 974 return DWARF_CB_ABORT;
975 } 975 }
976 } 976 }
977 977
978 return DWARF_CB_OK; 978 return DWARF_CB_OK;
979 } 979 }
980 980
981 /* Find probe points from debuginfo */ 981 /* Find probe points from debuginfo */
982 static int debuginfo__find_probes(struct debuginfo *dbg, 982 static int debuginfo__find_probes(struct debuginfo *dbg,
983 struct probe_finder *pf) 983 struct probe_finder *pf)
984 { 984 {
985 struct perf_probe_point *pp = &pf->pev->point; 985 struct perf_probe_point *pp = &pf->pev->point;
986 Dwarf_Off off, noff; 986 Dwarf_Off off, noff;
987 size_t cuhl; 987 size_t cuhl;
988 Dwarf_Die *diep; 988 Dwarf_Die *diep;
989 int ret = 0; 989 int ret = 0;
990 990
991 #if _ELFUTILS_PREREQ(0, 142) 991 #if _ELFUTILS_PREREQ(0, 142)
992 Elf *elf;
993 GElf_Ehdr ehdr;
994 GElf_Shdr shdr;
995
992 /* Get the call frame information from this dwarf */ 996 /* Get the call frame information from this dwarf */
993 pf->cfi = dwarf_getcfi_elf(dwarf_getelf(dbg->dbg)); 997 elf = dwarf_getelf(dbg->dbg);
998 if (elf == NULL)
999 return -EINVAL;
1000
1001 if (gelf_getehdr(elf, &ehdr) == NULL)
1002 return -EINVAL;
1003
1004 if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
1005 shdr.sh_type == SHT_PROGBITS) {
1006 pf->cfi = dwarf_getcfi_elf(elf);
1007 } else {
1008 pf->cfi = dwarf_getcfi(dbg->dbg);
1009 }
994 #endif 1010 #endif
995 1011
996 off = 0; 1012 off = 0;
997 pf->lcache = intlist__new(NULL); 1013 pf->lcache = intlist__new(NULL);
998 if (!pf->lcache) 1014 if (!pf->lcache)
999 return -ENOMEM; 1015 return -ENOMEM;
1000 1016
1001 /* Fastpath: lookup by function name from .debug_pubnames section */ 1017 /* Fastpath: lookup by function name from .debug_pubnames section */
1002 if (pp->function) { 1018 if (pp->function) {
1003 struct pubname_callback_param pubname_param = { 1019 struct pubname_callback_param pubname_param = {
1004 .function = pp->function, 1020 .function = pp->function,
1005 .file = pp->file, 1021 .file = pp->file,
1006 .cu_die = &pf->cu_die, 1022 .cu_die = &pf->cu_die,
1007 .sp_die = &pf->sp_die, 1023 .sp_die = &pf->sp_die,
1008 .found = 0, 1024 .found = 0,
1009 }; 1025 };
1010 struct dwarf_callback_param probe_param = { 1026 struct dwarf_callback_param probe_param = {
1011 .data = pf, 1027 .data = pf,
1012 }; 1028 };
1013 1029
1014 dwarf_getpubnames(dbg->dbg, pubname_search_cb, 1030 dwarf_getpubnames(dbg->dbg, pubname_search_cb,
1015 &pubname_param, 0); 1031 &pubname_param, 0);
1016 if (pubname_param.found) { 1032 if (pubname_param.found) {
1017 ret = probe_point_search_cb(&pf->sp_die, &probe_param); 1033 ret = probe_point_search_cb(&pf->sp_die, &probe_param);
1018 if (ret) 1034 if (ret)
1019 goto found; 1035 goto found;
1020 } 1036 }
1021 } 1037 }
1022 1038
1023 /* Loop on CUs (Compilation Unit) */ 1039 /* Loop on CUs (Compilation Unit) */
1024 while (!dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { 1040 while (!dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
1025 /* Get the DIE(Debugging Information Entry) of this CU */ 1041 /* Get the DIE(Debugging Information Entry) of this CU */
1026 diep = dwarf_offdie(dbg->dbg, off + cuhl, &pf->cu_die); 1042 diep = dwarf_offdie(dbg->dbg, off + cuhl, &pf->cu_die);
1027 if (!diep) 1043 if (!diep)
1028 continue; 1044 continue;
1029 1045
1030 /* Check if target file is included. */ 1046 /* Check if target file is included. */
1031 if (pp->file) 1047 if (pp->file)
1032 pf->fname = cu_find_realpath(&pf->cu_die, pp->file); 1048 pf->fname = cu_find_realpath(&pf->cu_die, pp->file);
1033 else 1049 else
1034 pf->fname = NULL; 1050 pf->fname = NULL;
1035 1051
1036 if (!pp->file || pf->fname) { 1052 if (!pp->file || pf->fname) {
1037 if (pp->function) 1053 if (pp->function)
1038 ret = find_probe_point_by_func(pf); 1054 ret = find_probe_point_by_func(pf);
1039 else if (pp->lazy_line) 1055 else if (pp->lazy_line)
1040 ret = find_probe_point_lazy(NULL, pf); 1056 ret = find_probe_point_lazy(NULL, pf);
1041 else { 1057 else {
1042 pf->lno = pp->line; 1058 pf->lno = pp->line;
1043 ret = find_probe_point_by_line(pf); 1059 ret = find_probe_point_by_line(pf);
1044 } 1060 }
1045 if (ret < 0) 1061 if (ret < 0)
1046 break; 1062 break;
1047 } 1063 }
1048 off = noff; 1064 off = noff;
1049 } 1065 }
1050 1066
1051 found: 1067 found:
1052 intlist__delete(pf->lcache); 1068 intlist__delete(pf->lcache);
1053 pf->lcache = NULL; 1069 pf->lcache = NULL;
1054 1070
1055 return ret; 1071 return ret;
1056 } 1072 }
1057 1073
1058 struct local_vars_finder { 1074 struct local_vars_finder {
1059 struct probe_finder *pf; 1075 struct probe_finder *pf;
1060 struct perf_probe_arg *args; 1076 struct perf_probe_arg *args;
1061 int max_args; 1077 int max_args;
1062 int nargs; 1078 int nargs;
1063 int ret; 1079 int ret;
1064 }; 1080 };
1065 1081
1066 /* Collect available variables in this scope */ 1082 /* Collect available variables in this scope */
1067 static int copy_variables_cb(Dwarf_Die *die_mem, void *data) 1083 static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
1068 { 1084 {
1069 struct local_vars_finder *vf = data; 1085 struct local_vars_finder *vf = data;
1070 struct probe_finder *pf = vf->pf; 1086 struct probe_finder *pf = vf->pf;
1071 int tag; 1087 int tag;
1072 1088
1073 tag = dwarf_tag(die_mem); 1089 tag = dwarf_tag(die_mem);
1074 if (tag == DW_TAG_formal_parameter || 1090 if (tag == DW_TAG_formal_parameter ||
1075 tag == DW_TAG_variable) { 1091 tag == DW_TAG_variable) {
1076 if (convert_variable_location(die_mem, vf->pf->addr, 1092 if (convert_variable_location(die_mem, vf->pf->addr,
1077 vf->pf->fb_ops, &pf->sp_die, 1093 vf->pf->fb_ops, &pf->sp_die,
1078 NULL) == 0) { 1094 NULL) == 0) {
1079 vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem); 1095 vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
1080 if (vf->args[vf->nargs].var == NULL) { 1096 if (vf->args[vf->nargs].var == NULL) {
1081 vf->ret = -ENOMEM; 1097 vf->ret = -ENOMEM;
1082 return DIE_FIND_CB_END; 1098 return DIE_FIND_CB_END;
1083 } 1099 }
1084 pr_debug(" %s", vf->args[vf->nargs].var); 1100 pr_debug(" %s", vf->args[vf->nargs].var);
1085 vf->nargs++; 1101 vf->nargs++;
1086 } 1102 }
1087 } 1103 }
1088 1104
1089 if (dwarf_haspc(die_mem, vf->pf->addr)) 1105 if (dwarf_haspc(die_mem, vf->pf->addr))
1090 return DIE_FIND_CB_CONTINUE; 1106 return DIE_FIND_CB_CONTINUE;
1091 else 1107 else
1092 return DIE_FIND_CB_SIBLING; 1108 return DIE_FIND_CB_SIBLING;
1093 } 1109 }
1094 1110
1095 static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf, 1111 static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf,
1096 struct perf_probe_arg *args) 1112 struct perf_probe_arg *args)
1097 { 1113 {
1098 Dwarf_Die die_mem; 1114 Dwarf_Die die_mem;
1099 int i; 1115 int i;
1100 int n = 0; 1116 int n = 0;
1101 struct local_vars_finder vf = {.pf = pf, .args = args, 1117 struct local_vars_finder vf = {.pf = pf, .args = args,
1102 .max_args = MAX_PROBE_ARGS, .ret = 0}; 1118 .max_args = MAX_PROBE_ARGS, .ret = 0};
1103 1119
1104 for (i = 0; i < pf->pev->nargs; i++) { 1120 for (i = 0; i < pf->pev->nargs; i++) {
1105 /* var never be NULL */ 1121 /* var never be NULL */
1106 if (strcmp(pf->pev->args[i].var, "$vars") == 0) { 1122 if (strcmp(pf->pev->args[i].var, "$vars") == 0) {
1107 pr_debug("Expanding $vars into:"); 1123 pr_debug("Expanding $vars into:");
1108 vf.nargs = n; 1124 vf.nargs = n;
1109 /* Special local variables */ 1125 /* Special local variables */
1110 die_find_child(sc_die, copy_variables_cb, (void *)&vf, 1126 die_find_child(sc_die, copy_variables_cb, (void *)&vf,
1111 &die_mem); 1127 &die_mem);
1112 pr_debug(" (%d)\n", vf.nargs - n); 1128 pr_debug(" (%d)\n", vf.nargs - n);
1113 if (vf.ret < 0) 1129 if (vf.ret < 0)
1114 return vf.ret; 1130 return vf.ret;
1115 n = vf.nargs; 1131 n = vf.nargs;
1116 } else { 1132 } else {
1117 /* Copy normal argument */ 1133 /* Copy normal argument */
1118 args[n] = pf->pev->args[i]; 1134 args[n] = pf->pev->args[i];
1119 n++; 1135 n++;
1120 } 1136 }
1121 } 1137 }
1122 return n; 1138 return n;
1123 } 1139 }
1124 1140
1125 /* Add a found probe point into trace event list */ 1141 /* Add a found probe point into trace event list */
1126 static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) 1142 static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1127 { 1143 {
1128 struct trace_event_finder *tf = 1144 struct trace_event_finder *tf =
1129 container_of(pf, struct trace_event_finder, pf); 1145 container_of(pf, struct trace_event_finder, pf);
1130 struct probe_trace_event *tev; 1146 struct probe_trace_event *tev;
1131 struct perf_probe_arg *args; 1147 struct perf_probe_arg *args;
1132 int ret, i; 1148 int ret, i;
1133 1149
1134 /* Check number of tevs */ 1150 /* Check number of tevs */
1135 if (tf->ntevs == tf->max_tevs) { 1151 if (tf->ntevs == tf->max_tevs) {
1136 pr_warning("Too many( > %d) probe point found.\n", 1152 pr_warning("Too many( > %d) probe point found.\n",
1137 tf->max_tevs); 1153 tf->max_tevs);
1138 return -ERANGE; 1154 return -ERANGE;
1139 } 1155 }
1140 tev = &tf->tevs[tf->ntevs++]; 1156 tev = &tf->tevs[tf->ntevs++];
1141 1157
1142 /* Trace point should be converted from subprogram DIE */ 1158 /* Trace point should be converted from subprogram DIE */
1143 ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr, 1159 ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr,
1144 pf->pev->point.retprobe, &tev->point); 1160 pf->pev->point.retprobe, &tev->point);
1145 if (ret < 0) 1161 if (ret < 0)
1146 return ret; 1162 return ret;
1147 1163
1148 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, 1164 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
1149 tev->point.offset); 1165 tev->point.offset);
1150 1166
1151 /* Expand special probe argument if exist */ 1167 /* Expand special probe argument if exist */
1152 args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS); 1168 args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS);
1153 if (args == NULL) 1169 if (args == NULL)
1154 return -ENOMEM; 1170 return -ENOMEM;
1155 1171
1156 ret = expand_probe_args(sc_die, pf, args); 1172 ret = expand_probe_args(sc_die, pf, args);
1157 if (ret < 0) 1173 if (ret < 0)
1158 goto end; 1174 goto end;
1159 1175
1160 tev->nargs = ret; 1176 tev->nargs = ret;
1161 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); 1177 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
1162 if (tev->args == NULL) { 1178 if (tev->args == NULL) {
1163 ret = -ENOMEM; 1179 ret = -ENOMEM;
1164 goto end; 1180 goto end;
1165 } 1181 }
1166 1182
1167 /* Find each argument */ 1183 /* Find each argument */
1168 for (i = 0; i < tev->nargs; i++) { 1184 for (i = 0; i < tev->nargs; i++) {
1169 pf->pvar = &args[i]; 1185 pf->pvar = &args[i];
1170 pf->tvar = &tev->args[i]; 1186 pf->tvar = &tev->args[i];
1171 /* Variable should be found from scope DIE */ 1187 /* Variable should be found from scope DIE */
1172 ret = find_variable(sc_die, pf); 1188 ret = find_variable(sc_die, pf);
1173 if (ret != 0) 1189 if (ret != 0)
1174 break; 1190 break;
1175 } 1191 }
1176 1192
1177 end: 1193 end:
1178 free(args); 1194 free(args);
1179 return ret; 1195 return ret;
1180 } 1196 }
1181 1197
1182 /* Find probe_trace_events specified by perf_probe_event from debuginfo */ 1198 /* Find probe_trace_events specified by perf_probe_event from debuginfo */
1183 int debuginfo__find_trace_events(struct debuginfo *dbg, 1199 int debuginfo__find_trace_events(struct debuginfo *dbg,
1184 struct perf_probe_event *pev, 1200 struct perf_probe_event *pev,
1185 struct probe_trace_event **tevs, int max_tevs) 1201 struct probe_trace_event **tevs, int max_tevs)
1186 { 1202 {
1187 struct trace_event_finder tf = { 1203 struct trace_event_finder tf = {
1188 .pf = {.pev = pev, .callback = add_probe_trace_event}, 1204 .pf = {.pev = pev, .callback = add_probe_trace_event},
1189 .mod = dbg->mod, .max_tevs = max_tevs}; 1205 .mod = dbg->mod, .max_tevs = max_tevs};
1190 int ret; 1206 int ret;
1191 1207
1192 /* Allocate result tevs array */ 1208 /* Allocate result tevs array */
1193 *tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs); 1209 *tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs);
1194 if (*tevs == NULL) 1210 if (*tevs == NULL)
1195 return -ENOMEM; 1211 return -ENOMEM;
1196 1212
1197 tf.tevs = *tevs; 1213 tf.tevs = *tevs;
1198 tf.ntevs = 0; 1214 tf.ntevs = 0;
1199 1215
1200 ret = debuginfo__find_probes(dbg, &tf.pf); 1216 ret = debuginfo__find_probes(dbg, &tf.pf);
1201 if (ret < 0) { 1217 if (ret < 0) {
1202 zfree(tevs); 1218 zfree(tevs);
1203 return ret; 1219 return ret;
1204 } 1220 }
1205 1221
1206 return (ret < 0) ? ret : tf.ntevs; 1222 return (ret < 0) ? ret : tf.ntevs;
1207 } 1223 }
1208 1224
1209 #define MAX_VAR_LEN 64 1225 #define MAX_VAR_LEN 64
1210 1226
1211 /* Collect available variables in this scope */ 1227 /* Collect available variables in this scope */
1212 static int collect_variables_cb(Dwarf_Die *die_mem, void *data) 1228 static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1213 { 1229 {
1214 struct available_var_finder *af = data; 1230 struct available_var_finder *af = data;
1215 struct variable_list *vl; 1231 struct variable_list *vl;
1216 char buf[MAX_VAR_LEN]; 1232 char buf[MAX_VAR_LEN];
1217 int tag, ret; 1233 int tag, ret;
1218 1234
1219 vl = &af->vls[af->nvls - 1]; 1235 vl = &af->vls[af->nvls - 1];
1220 1236
1221 tag = dwarf_tag(die_mem); 1237 tag = dwarf_tag(die_mem);
1222 if (tag == DW_TAG_formal_parameter || 1238 if (tag == DW_TAG_formal_parameter ||
1223 tag == DW_TAG_variable) { 1239 tag == DW_TAG_variable) {
1224 ret = convert_variable_location(die_mem, af->pf.addr, 1240 ret = convert_variable_location(die_mem, af->pf.addr,
1225 af->pf.fb_ops, &af->pf.sp_die, 1241 af->pf.fb_ops, &af->pf.sp_die,
1226 NULL); 1242 NULL);
1227 if (ret == 0) { 1243 if (ret == 0) {
1228 ret = die_get_varname(die_mem, buf, MAX_VAR_LEN); 1244 ret = die_get_varname(die_mem, buf, MAX_VAR_LEN);
1229 pr_debug2("Add new var: %s\n", buf); 1245 pr_debug2("Add new var: %s\n", buf);
1230 if (ret > 0) 1246 if (ret > 0)
1231 strlist__add(vl->vars, buf); 1247 strlist__add(vl->vars, buf);
1232 } 1248 }
1233 } 1249 }
1234 1250
1235 if (af->child && dwarf_haspc(die_mem, af->pf.addr)) 1251 if (af->child && dwarf_haspc(die_mem, af->pf.addr))
1236 return DIE_FIND_CB_CONTINUE; 1252 return DIE_FIND_CB_CONTINUE;
1237 else 1253 else
1238 return DIE_FIND_CB_SIBLING; 1254 return DIE_FIND_CB_SIBLING;
1239 } 1255 }
1240 1256
1241 /* Add a found vars into available variables list */ 1257 /* Add a found vars into available variables list */
1242 static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) 1258 static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
1243 { 1259 {
1244 struct available_var_finder *af = 1260 struct available_var_finder *af =
1245 container_of(pf, struct available_var_finder, pf); 1261 container_of(pf, struct available_var_finder, pf);
1246 struct variable_list *vl; 1262 struct variable_list *vl;
1247 Dwarf_Die die_mem; 1263 Dwarf_Die die_mem;
1248 int ret; 1264 int ret;
1249 1265
1250 /* Check number of tevs */ 1266 /* Check number of tevs */
1251 if (af->nvls == af->max_vls) { 1267 if (af->nvls == af->max_vls) {
1252 pr_warning("Too many( > %d) probe point found.\n", af->max_vls); 1268 pr_warning("Too many( > %d) probe point found.\n", af->max_vls);
1253 return -ERANGE; 1269 return -ERANGE;
1254 } 1270 }
1255 vl = &af->vls[af->nvls++]; 1271 vl = &af->vls[af->nvls++];
1256 1272
1257 /* Trace point should be converted from subprogram DIE */ 1273 /* Trace point should be converted from subprogram DIE */
1258 ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr, 1274 ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr,
1259 pf->pev->point.retprobe, &vl->point); 1275 pf->pev->point.retprobe, &vl->point);
1260 if (ret < 0) 1276 if (ret < 0)
1261 return ret; 1277 return ret;
1262 1278
1263 pr_debug("Probe point found: %s+%lu\n", vl->point.symbol, 1279 pr_debug("Probe point found: %s+%lu\n", vl->point.symbol,
1264 vl->point.offset); 1280 vl->point.offset);
1265 1281
1266 /* Find local variables */ 1282 /* Find local variables */
1267 vl->vars = strlist__new(true, NULL); 1283 vl->vars = strlist__new(true, NULL);
1268 if (vl->vars == NULL) 1284 if (vl->vars == NULL)
1269 return -ENOMEM; 1285 return -ENOMEM;
1270 af->child = true; 1286 af->child = true;
1271 die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem); 1287 die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem);
1272 1288
1273 /* Find external variables */ 1289 /* Find external variables */
1274 if (!af->externs) 1290 if (!af->externs)
1275 goto out; 1291 goto out;
1276 /* Don't need to search child DIE for externs. */ 1292 /* Don't need to search child DIE for externs. */
1277 af->child = false; 1293 af->child = false;
1278 die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem); 1294 die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem);
1279 1295
1280 out: 1296 out:
1281 if (strlist__empty(vl->vars)) { 1297 if (strlist__empty(vl->vars)) {
1282 strlist__delete(vl->vars); 1298 strlist__delete(vl->vars);
1283 vl->vars = NULL; 1299 vl->vars = NULL;
1284 } 1300 }
1285 1301
1286 return ret; 1302 return ret;
1287 } 1303 }
1288 1304
1289 /* 1305 /*
1290 * Find available variables at given probe point 1306 * Find available variables at given probe point
1291 * Return the number of found probe points. Return 0 if there is no 1307 * Return the number of found probe points. Return 0 if there is no
1292 * matched probe point. Return <0 if an error occurs. 1308 * matched probe point. Return <0 if an error occurs.
1293 */ 1309 */
1294 int debuginfo__find_available_vars_at(struct debuginfo *dbg, 1310 int debuginfo__find_available_vars_at(struct debuginfo *dbg,
1295 struct perf_probe_event *pev, 1311 struct perf_probe_event *pev,
1296 struct variable_list **vls, 1312 struct variable_list **vls,
1297 int max_vls, bool externs) 1313 int max_vls, bool externs)
1298 { 1314 {
1299 struct available_var_finder af = { 1315 struct available_var_finder af = {
1300 .pf = {.pev = pev, .callback = add_available_vars}, 1316 .pf = {.pev = pev, .callback = add_available_vars},
1301 .mod = dbg->mod, 1317 .mod = dbg->mod,
1302 .max_vls = max_vls, .externs = externs}; 1318 .max_vls = max_vls, .externs = externs};
1303 int ret; 1319 int ret;
1304 1320
1305 /* Allocate result vls array */ 1321 /* Allocate result vls array */
1306 *vls = zalloc(sizeof(struct variable_list) * max_vls); 1322 *vls = zalloc(sizeof(struct variable_list) * max_vls);
1307 if (*vls == NULL) 1323 if (*vls == NULL)
1308 return -ENOMEM; 1324 return -ENOMEM;
1309 1325
1310 af.vls = *vls; 1326 af.vls = *vls;
1311 af.nvls = 0; 1327 af.nvls = 0;
1312 1328
1313 ret = debuginfo__find_probes(dbg, &af.pf); 1329 ret = debuginfo__find_probes(dbg, &af.pf);
1314 if (ret < 0) { 1330 if (ret < 0) {
1315 /* Free vlist for error */ 1331 /* Free vlist for error */
1316 while (af.nvls--) { 1332 while (af.nvls--) {
1317 zfree(&af.vls[af.nvls].point.symbol); 1333 zfree(&af.vls[af.nvls].point.symbol);
1318 strlist__delete(af.vls[af.nvls].vars); 1334 strlist__delete(af.vls[af.nvls].vars);
1319 } 1335 }
1320 zfree(vls); 1336 zfree(vls);
1321 return ret; 1337 return ret;
1322 } 1338 }
1323 1339
1324 return (ret < 0) ? ret : af.nvls; 1340 return (ret < 0) ? ret : af.nvls;
1325 } 1341 }
1326 1342
1327 /* Reverse search */ 1343 /* Reverse search */
1328 int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, 1344 int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
1329 struct perf_probe_point *ppt) 1345 struct perf_probe_point *ppt)
1330 { 1346 {
1331 Dwarf_Die cudie, spdie, indie; 1347 Dwarf_Die cudie, spdie, indie;
1332 Dwarf_Addr _addr = 0, baseaddr = 0; 1348 Dwarf_Addr _addr = 0, baseaddr = 0;
1333 const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; 1349 const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
1334 int baseline = 0, lineno = 0, ret = 0; 1350 int baseline = 0, lineno = 0, ret = 0;
1335 1351
1336 /* Adjust address with bias */ 1352 /* Adjust address with bias */
1337 addr += dbg->bias; 1353 addr += dbg->bias;
1338 1354
1339 /* Find cu die */ 1355 /* Find cu die */
1340 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr - dbg->bias, &cudie)) { 1356 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr - dbg->bias, &cudie)) {
1341 pr_warning("Failed to find debug information for address %lx\n", 1357 pr_warning("Failed to find debug information for address %lx\n",
1342 addr); 1358 addr);
1343 ret = -EINVAL; 1359 ret = -EINVAL;
1344 goto end; 1360 goto end;
1345 } 1361 }
1346 1362
1347 /* Find a corresponding line (filename and lineno) */ 1363 /* Find a corresponding line (filename and lineno) */
1348 cu_find_lineinfo(&cudie, addr, &fname, &lineno); 1364 cu_find_lineinfo(&cudie, addr, &fname, &lineno);
1349 /* Don't care whether it failed or not */ 1365 /* Don't care whether it failed or not */
1350 1366
1351 /* Find a corresponding function (name, baseline and baseaddr) */ 1367 /* Find a corresponding function (name, baseline and baseaddr) */
1352 if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) { 1368 if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) {
1353 /* Get function entry information */ 1369 /* Get function entry information */
1354 func = basefunc = dwarf_diename(&spdie); 1370 func = basefunc = dwarf_diename(&spdie);
1355 if (!func || 1371 if (!func ||
1356 dwarf_entrypc(&spdie, &baseaddr) != 0 || 1372 dwarf_entrypc(&spdie, &baseaddr) != 0 ||
1357 dwarf_decl_line(&spdie, &baseline) != 0) { 1373 dwarf_decl_line(&spdie, &baseline) != 0) {
1358 lineno = 0; 1374 lineno = 0;
1359 goto post; 1375 goto post;
1360 } 1376 }
1361 1377
1362 fname = dwarf_decl_file(&spdie); 1378 fname = dwarf_decl_file(&spdie);
1363 if (addr == (unsigned long)baseaddr) { 1379 if (addr == (unsigned long)baseaddr) {
1364 /* Function entry - Relative line number is 0 */ 1380 /* Function entry - Relative line number is 0 */
1365 lineno = baseline; 1381 lineno = baseline;
1366 goto post; 1382 goto post;
1367 } 1383 }
1368 1384
1369 /* Track down the inline functions step by step */ 1385 /* Track down the inline functions step by step */
1370 while (die_find_top_inlinefunc(&spdie, (Dwarf_Addr)addr, 1386 while (die_find_top_inlinefunc(&spdie, (Dwarf_Addr)addr,
1371 &indie)) { 1387 &indie)) {
1372 /* There is an inline function */ 1388 /* There is an inline function */
1373 if (dwarf_entrypc(&indie, &_addr) == 0 && 1389 if (dwarf_entrypc(&indie, &_addr) == 0 &&
1374 _addr == addr) { 1390 _addr == addr) {
1375 /* 1391 /*
1376 * addr is at an inline function entry. 1392 * addr is at an inline function entry.
1377 * In this case, lineno should be the call-site 1393 * In this case, lineno should be the call-site
1378 * line number. (overwrite lineinfo) 1394 * line number. (overwrite lineinfo)
1379 */ 1395 */
1380 lineno = die_get_call_lineno(&indie); 1396 lineno = die_get_call_lineno(&indie);
1381 fname = die_get_call_file(&indie); 1397 fname = die_get_call_file(&indie);
1382 break; 1398 break;
1383 } else { 1399 } else {
1384 /* 1400 /*
1385 * addr is in an inline function body. 1401 * addr is in an inline function body.
1386 * Since lineno points one of the lines 1402 * Since lineno points one of the lines
1387 * of the inline function, baseline should 1403 * of the inline function, baseline should
1388 * be the entry line of the inline function. 1404 * be the entry line of the inline function.
1389 */ 1405 */
1390 tmp = dwarf_diename(&indie); 1406 tmp = dwarf_diename(&indie);
1391 if (!tmp || 1407 if (!tmp ||
1392 dwarf_decl_line(&indie, &baseline) != 0) 1408 dwarf_decl_line(&indie, &baseline) != 0)
1393 break; 1409 break;
1394 func = tmp; 1410 func = tmp;
1395 spdie = indie; 1411 spdie = indie;
1396 } 1412 }
1397 } 1413 }
1398 /* Verify the lineno and baseline are in a same file */ 1414 /* Verify the lineno and baseline are in a same file */
1399 tmp = dwarf_decl_file(&spdie); 1415 tmp = dwarf_decl_file(&spdie);
1400 if (!tmp || strcmp(tmp, fname) != 0) 1416 if (!tmp || strcmp(tmp, fname) != 0)
1401 lineno = 0; 1417 lineno = 0;
1402 } 1418 }
1403 1419
1404 post: 1420 post:
1405 /* Make a relative line number or an offset */ 1421 /* Make a relative line number or an offset */
1406 if (lineno) 1422 if (lineno)
1407 ppt->line = lineno - baseline; 1423 ppt->line = lineno - baseline;
1408 else if (basefunc) { 1424 else if (basefunc) {
1409 ppt->offset = addr - (unsigned long)baseaddr; 1425 ppt->offset = addr - (unsigned long)baseaddr;
1410 func = basefunc; 1426 func = basefunc;
1411 } 1427 }
1412 1428
1413 /* Duplicate strings */ 1429 /* Duplicate strings */
1414 if (func) { 1430 if (func) {
1415 ppt->function = strdup(func); 1431 ppt->function = strdup(func);
1416 if (ppt->function == NULL) { 1432 if (ppt->function == NULL) {
1417 ret = -ENOMEM; 1433 ret = -ENOMEM;
1418 goto end; 1434 goto end;
1419 } 1435 }
1420 } 1436 }
1421 if (fname) { 1437 if (fname) {
1422 ppt->file = strdup(fname); 1438 ppt->file = strdup(fname);
1423 if (ppt->file == NULL) { 1439 if (ppt->file == NULL) {
1424 zfree(&ppt->function); 1440 zfree(&ppt->function);
1425 ret = -ENOMEM; 1441 ret = -ENOMEM;
1426 goto end; 1442 goto end;
1427 } 1443 }
1428 } 1444 }
1429 end: 1445 end:
1430 if (ret == 0 && (fname || func)) 1446 if (ret == 0 && (fname || func))
1431 ret = 1; /* Found a point */ 1447 ret = 1; /* Found a point */
1432 return ret; 1448 return ret;
1433 } 1449 }
1434 1450
1435 /* Add a line and store the src path */ 1451 /* Add a line and store the src path */
1436 static int line_range_add_line(const char *src, unsigned int lineno, 1452 static int line_range_add_line(const char *src, unsigned int lineno,
1437 struct line_range *lr) 1453 struct line_range *lr)
1438 { 1454 {
1439 /* Copy source path */ 1455 /* Copy source path */
1440 if (!lr->path) { 1456 if (!lr->path) {
1441 lr->path = strdup(src); 1457 lr->path = strdup(src);
1442 if (lr->path == NULL) 1458 if (lr->path == NULL)
1443 return -ENOMEM; 1459 return -ENOMEM;
1444 } 1460 }
1445 return intlist__add(lr->line_list, lineno); 1461 return intlist__add(lr->line_list, lineno);
1446 } 1462 }
1447 1463
1448 static int line_range_walk_cb(const char *fname, int lineno, 1464 static int line_range_walk_cb(const char *fname, int lineno,
1449 Dwarf_Addr addr __maybe_unused, 1465 Dwarf_Addr addr __maybe_unused,
1450 void *data) 1466 void *data)
1451 { 1467 {
1452 struct line_finder *lf = data; 1468 struct line_finder *lf = data;
1453 int err; 1469 int err;
1454 1470
1455 if ((strtailcmp(fname, lf->fname) != 0) || 1471 if ((strtailcmp(fname, lf->fname) != 0) ||
1456 (lf->lno_s > lineno || lf->lno_e < lineno)) 1472 (lf->lno_s > lineno || lf->lno_e < lineno))
1457 return 0; 1473 return 0;
1458 1474
1459 err = line_range_add_line(fname, lineno, lf->lr); 1475 err = line_range_add_line(fname, lineno, lf->lr);
1460 if (err < 0 && err != -EEXIST) 1476 if (err < 0 && err != -EEXIST)
1461 return err; 1477 return err;
1462 1478
1463 return 0; 1479 return 0;
1464 } 1480 }
1465 1481
1466 /* Find line range from its line number */ 1482 /* Find line range from its line number */
1467 static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) 1483 static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1468 { 1484 {
1469 int ret; 1485 int ret;
1470 1486
1471 ret = die_walk_lines(sp_die ?: &lf->cu_die, line_range_walk_cb, lf); 1487 ret = die_walk_lines(sp_die ?: &lf->cu_die, line_range_walk_cb, lf);
1472 1488
1473 /* Update status */ 1489 /* Update status */
1474 if (ret >= 0) 1490 if (ret >= 0)
1475 if (!intlist__empty(lf->lr->line_list)) 1491 if (!intlist__empty(lf->lr->line_list))
1476 ret = lf->found = 1; 1492 ret = lf->found = 1;
1477 else 1493 else
1478 ret = 0; /* Lines are not found */ 1494 ret = 0; /* Lines are not found */
1479 else { 1495 else {
1480 zfree(&lf->lr->path); 1496 zfree(&lf->lr->path);
1481 } 1497 }
1482 return ret; 1498 return ret;
1483 } 1499 }
1484 1500
1485 static int line_range_inline_cb(Dwarf_Die *in_die, void *data) 1501 static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
1486 { 1502 {
1487 int ret = find_line_range_by_line(in_die, data); 1503 int ret = find_line_range_by_line(in_die, data);
1488 1504
1489 /* 1505 /*
1490 * We have to check all instances of inlined function, because 1506 * We have to check all instances of inlined function, because
1491 * some execution paths can be optimized out depends on the 1507 * some execution paths can be optimized out depends on the
1492 * function argument of instances. However, if an error occurs, 1508 * function argument of instances. However, if an error occurs,
1493 * it should be handled by the caller. 1509 * it should be handled by the caller.
1494 */ 1510 */
1495 return ret < 0 ? ret : 0; 1511 return ret < 0 ? ret : 0;
1496 } 1512 }
1497 1513
1498 /* Search function definition from function name */ 1514 /* Search function definition from function name */
1499 static int line_range_search_cb(Dwarf_Die *sp_die, void *data) 1515 static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1500 { 1516 {
1501 struct dwarf_callback_param *param = data; 1517 struct dwarf_callback_param *param = data;
1502 struct line_finder *lf = param->data; 1518 struct line_finder *lf = param->data;
1503 struct line_range *lr = lf->lr; 1519 struct line_range *lr = lf->lr;
1504 1520
1505 /* Check declared file */ 1521 /* Check declared file */
1506 if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die))) 1522 if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
1507 return DWARF_CB_OK; 1523 return DWARF_CB_OK;
1508 1524
1509 if (die_is_func_def(sp_die) && 1525 if (die_is_func_def(sp_die) &&
1510 die_compare_name(sp_die, lr->function)) { 1526 die_compare_name(sp_die, lr->function)) {
1511 lf->fname = dwarf_decl_file(sp_die); 1527 lf->fname = dwarf_decl_file(sp_die);
1512 dwarf_decl_line(sp_die, &lr->offset); 1528 dwarf_decl_line(sp_die, &lr->offset);
1513 pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset); 1529 pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
1514 lf->lno_s = lr->offset + lr->start; 1530 lf->lno_s = lr->offset + lr->start;
1515 if (lf->lno_s < 0) /* Overflow */ 1531 if (lf->lno_s < 0) /* Overflow */
1516 lf->lno_s = INT_MAX; 1532 lf->lno_s = INT_MAX;
1517 lf->lno_e = lr->offset + lr->end; 1533 lf->lno_e = lr->offset + lr->end;
1518 if (lf->lno_e < 0) /* Overflow */ 1534 if (lf->lno_e < 0) /* Overflow */
1519 lf->lno_e = INT_MAX; 1535 lf->lno_e = INT_MAX;
1520 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e); 1536 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
1521 lr->start = lf->lno_s; 1537 lr->start = lf->lno_s;
1522 lr->end = lf->lno_e; 1538 lr->end = lf->lno_e;
1523 if (dwarf_func_inline(sp_die)) 1539 if (dwarf_func_inline(sp_die))
1524 param->retval = die_walk_instances(sp_die, 1540 param->retval = die_walk_instances(sp_die,
1525 line_range_inline_cb, lf); 1541 line_range_inline_cb, lf);
1526 else 1542 else
1527 param->retval = find_line_range_by_line(sp_die, lf); 1543 param->retval = find_line_range_by_line(sp_die, lf);
1528 return DWARF_CB_ABORT; 1544 return DWARF_CB_ABORT;
1529 } 1545 }
1530 return DWARF_CB_OK; 1546 return DWARF_CB_OK;
1531 } 1547 }
1532 1548
1533 static int find_line_range_by_func(struct line_finder *lf) 1549 static int find_line_range_by_func(struct line_finder *lf)
1534 { 1550 {
1535 struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0}; 1551 struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
1536 dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0); 1552 dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
1537 return param.retval; 1553 return param.retval;
1538 } 1554 }
1539 1555
1540 int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr) 1556 int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr)
1541 { 1557 {
1542 struct line_finder lf = {.lr = lr, .found = 0}; 1558 struct line_finder lf = {.lr = lr, .found = 0};
1543 int ret = 0; 1559 int ret = 0;
1544 Dwarf_Off off = 0, noff; 1560 Dwarf_Off off = 0, noff;
1545 size_t cuhl; 1561 size_t cuhl;
1546 Dwarf_Die *diep; 1562 Dwarf_Die *diep;
1547 const char *comp_dir; 1563 const char *comp_dir;
1548 1564
1549 /* Fastpath: lookup by function name from .debug_pubnames section */ 1565 /* Fastpath: lookup by function name from .debug_pubnames section */
1550 if (lr->function) { 1566 if (lr->function) {
1551 struct pubname_callback_param pubname_param = { 1567 struct pubname_callback_param pubname_param = {
1552 .function = lr->function, .file = lr->file, 1568 .function = lr->function, .file = lr->file,
1553 .cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0}; 1569 .cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0};
1554 struct dwarf_callback_param line_range_param = { 1570 struct dwarf_callback_param line_range_param = {
1555 .data = (void *)&lf, .retval = 0}; 1571 .data = (void *)&lf, .retval = 0};
1556 1572
1557 dwarf_getpubnames(dbg->dbg, pubname_search_cb, 1573 dwarf_getpubnames(dbg->dbg, pubname_search_cb,
1558 &pubname_param, 0); 1574 &pubname_param, 0);
1559 if (pubname_param.found) { 1575 if (pubname_param.found) {
1560 line_range_search_cb(&lf.sp_die, &line_range_param); 1576 line_range_search_cb(&lf.sp_die, &line_range_param);
1561 if (lf.found) 1577 if (lf.found)
1562 goto found; 1578 goto found;
1563 } 1579 }
1564 } 1580 }
1565 1581
1566 /* Loop on CUs (Compilation Unit) */ 1582 /* Loop on CUs (Compilation Unit) */
1567 while (!lf.found && ret >= 0) { 1583 while (!lf.found && ret >= 0) {
1568 if (dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, 1584 if (dwarf_nextcu(dbg->dbg, off, &noff, &cuhl,
1569 NULL, NULL, NULL) != 0) 1585 NULL, NULL, NULL) != 0)
1570 break; 1586 break;
1571 1587
1572 /* Get the DIE(Debugging Information Entry) of this CU */ 1588 /* Get the DIE(Debugging Information Entry) of this CU */
1573 diep = dwarf_offdie(dbg->dbg, off + cuhl, &lf.cu_die); 1589 diep = dwarf_offdie(dbg->dbg, off + cuhl, &lf.cu_die);
1574 if (!diep) 1590 if (!diep)
1575 continue; 1591 continue;
1576 1592
1577 /* Check if target file is included. */ 1593 /* Check if target file is included. */
1578 if (lr->file) 1594 if (lr->file)
1579 lf.fname = cu_find_realpath(&lf.cu_die, lr->file); 1595 lf.fname = cu_find_realpath(&lf.cu_die, lr->file);
1580 else 1596 else
1581 lf.fname = 0; 1597 lf.fname = 0;
1582 1598
1583 if (!lr->file || lf.fname) { 1599 if (!lr->file || lf.fname) {
1584 if (lr->function) 1600 if (lr->function)
1585 ret = find_line_range_by_func(&lf); 1601 ret = find_line_range_by_func(&lf);
1586 else { 1602 else {
1587 lf.lno_s = lr->start; 1603 lf.lno_s = lr->start;
1588 lf.lno_e = lr->end; 1604 lf.lno_e = lr->end;
1589 ret = find_line_range_by_line(NULL, &lf); 1605 ret = find_line_range_by_line(NULL, &lf);
1590 } 1606 }
1591 } 1607 }
1592 off = noff; 1608 off = noff;
1593 } 1609 }
1594 1610
1595 found: 1611 found:
1596 /* Store comp_dir */ 1612 /* Store comp_dir */
1597 if (lf.found) { 1613 if (lf.found) {
1598 comp_dir = cu_get_comp_dir(&lf.cu_die); 1614 comp_dir = cu_get_comp_dir(&lf.cu_die);
1599 if (comp_dir) { 1615 if (comp_dir) {
1600 lr->comp_dir = strdup(comp_dir); 1616 lr->comp_dir = strdup(comp_dir);
1601 if (!lr->comp_dir) 1617 if (!lr->comp_dir)
1602 ret = -ENOMEM; 1618 ret = -ENOMEM;
1603 } 1619 }
1604 } 1620 }
1605 1621
1606 pr_debug("path: %s\n", lr->path); 1622 pr_debug("path: %s\n", lr->path);
1607 return (ret < 0) ? ret : lf.found; 1623 return (ret < 0) ? ret : lf.found;
1608 } 1624 }
1609 1625
1610 1626