perf probe: Function style fix
[linux-2.6-block.git] / tools / perf / util / probe-finder.c
CommitLineData
4ea42b18
MH
1/*
2 * probe-finder.c : C expression to kprobe event converter
3 *
4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
5 *
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
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
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
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21
22#include <sys/utsname.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <fcntl.h>
26#include <errno.h>
27#include <stdio.h>
28#include <unistd.h>
29#include <getopt.h>
30#include <stdlib.h>
31#include <string.h>
32#include <stdarg.h>
33#include <ctype.h>
cd932c59 34#include <dwarf-regs.h>
074fc0e4 35
89c69c0e
MH
36#include "event.h"
37#include "debug.h"
074fc0e4 38#include "util.h"
9ed7e1b8 39#include "symbol.h"
4ea42b18
MH
40#include "probe-finder.h"
41
4984912e
MH
42/* Kprobe tracer basic type is up to u64 */
43#define MAX_BASIC_TYPE_BITS 64
44
4ea42b18
MH
45/*
46 * Compare the tail of two strings.
47 * Return 0 if whole of either string is same as another's tail part.
48 */
49static int strtailcmp(const char *s1, const char *s2)
50{
51 int i1 = strlen(s1);
52 int i2 = strlen(s2);
d56728b8 53 while (--i1 >= 0 && --i2 >= 0) {
4ea42b18
MH
54 if (s1[i1] != s2[i2])
55 return s1[i1] - s2[i2];
56 }
57 return 0;
58}
59
2a9c8c36
MH
60/* Line number list operations */
61
62/* Add a line to line number list */
d3b63d7a 63static int line_list__add_line(struct list_head *head, int line)
2a9c8c36
MH
64{
65 struct line_node *ln;
66 struct list_head *p;
67
68 /* Reverse search, because new line will be the last one */
69 list_for_each_entry_reverse(ln, head, list) {
70 if (ln->line < line) {
71 p = &ln->list;
72 goto found;
73 } else if (ln->line == line) /* Already exist */
e334016f 74 return 1;
2a9c8c36
MH
75 }
76 /* List is empty, or the smallest entry */
77 p = head;
78found:
79 pr_debug("line list: add a line %u\n", line);
e334016f
MH
80 ln = zalloc(sizeof(struct line_node));
81 if (ln == NULL)
82 return -ENOMEM;
2a9c8c36
MH
83 ln->line = line;
84 INIT_LIST_HEAD(&ln->list);
85 list_add(&ln->list, p);
e334016f 86 return 0;
2a9c8c36
MH
87}
88
89/* Check if the line in line number list */
d3b63d7a 90static int line_list__has_line(struct list_head *head, int line)
2a9c8c36
MH
91{
92 struct line_node *ln;
93
94 /* Reverse search, because new line will be the last one */
95 list_for_each_entry(ln, head, list)
96 if (ln->line == line)
97 return 1;
98
99 return 0;
100}
101
102/* Init line number list */
103static void line_list__init(struct list_head *head)
104{
105 INIT_LIST_HEAD(head);
106}
107
108/* Free line number list */
109static void line_list__free(struct list_head *head)
110{
111 struct line_node *ln;
112 while (!list_empty(head)) {
113 ln = list_first_entry(head, struct line_node, list);
114 list_del(&ln->list);
115 free(ln);
116 }
117}
118
119/* Dwarf wrappers */
120
121/* Find the realpath of the target file. */
122static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
4ea42b18 123{
804b3606
MH
124 Dwarf_Files *files;
125 size_t nfiles, i;
accd3cc4 126 const char *src = NULL;
4ea42b18
MH
127 int ret;
128
129 if (!fname)
2a9c8c36 130 return NULL;
4ea42b18 131
804b3606 132 ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
2a9c8c36
MH
133 if (ret != 0)
134 return NULL;
135
136 for (i = 0; i < nfiles; i++) {
137 src = dwarf_filesrc(files, i, NULL, NULL);
138 if (strtailcmp(src, fname) == 0)
139 break;
4ea42b18 140 }
c9e38582
MH
141 if (i == nfiles)
142 return NULL;
2a9c8c36 143 return src;
4ea42b18
MH
144}
145
6a330a3c
MH
146/* Get DW_AT_comp_dir (should be NULL with older gcc) */
147static const char *cu_get_comp_dir(Dwarf_Die *cu_die)
148{
149 Dwarf_Attribute attr;
150 if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL)
151 return NULL;
152 return dwarf_formstring(&attr);
153}
154
016f262e
MH
155/* Compare diename and tname */
156static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
157{
158 const char *name;
159 name = dwarf_diename(dw_die);
82175633 160 return name ? (strcmp(tname, name) == 0) : false;
016f262e
MH
161}
162
4046b8bb
MH
163/* Get type die */
164static Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
165{
166 Dwarf_Attribute attr;
167
168 if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
169 dwarf_formref_die(&attr, die_mem))
170 return die_mem;
171 else
172 return NULL;
173}
174
cf6eb489
MH
175/* Get a type die, but skip qualifiers */
176static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
7df2f329 177{
7df2f329
MH
178 int tag;
179
180 do {
4046b8bb
MH
181 vr_die = die_get_type(vr_die, die_mem);
182 if (!vr_die)
183 break;
184 tag = dwarf_tag(vr_die);
7df2f329
MH
185 } while (tag == DW_TAG_const_type ||
186 tag == DW_TAG_restrict_type ||
187 tag == DW_TAG_volatile_type ||
cf6eb489
MH
188 tag == DW_TAG_shared_type);
189
190 return vr_die;
191}
192
193/* Get a type die, but skip qualifiers and typedef */
194static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
195{
196 do {
197 vr_die = __die_get_real_type(vr_die, die_mem);
198 } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
7df2f329 199
4046b8bb 200 return vr_die;
7df2f329
MH
201}
202
4984912e
MH
203static bool die_is_signed_type(Dwarf_Die *tp_die)
204{
205 Dwarf_Attribute attr;
206 Dwarf_Word ret;
207
208 if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL ||
209 dwarf_formudata(&attr, &ret) != 0)
210 return false;
211
212 return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
213 ret == DW_ATE_signed_fixed);
214}
215
216static int die_get_byte_size(Dwarf_Die *tp_die)
217{
218 Dwarf_Attribute attr;
219 Dwarf_Word ret;
220
221 if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL ||
222 dwarf_formudata(&attr, &ret) != 0)
223 return 0;
224
225 return (int)ret;
226}
227
de1439d8
MH
228/* Get data_member_location offset */
229static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
230{
231 Dwarf_Attribute attr;
232 Dwarf_Op *expr;
233 size_t nexpr;
234 int ret;
235
236 if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
237 return -ENOENT;
238
239 if (dwarf_formudata(&attr, offs) != 0) {
240 /* DW_AT_data_member_location should be DW_OP_plus_uconst */
241 ret = dwarf_getlocation(&attr, &expr, &nexpr);
242 if (ret < 0 || nexpr == 0)
243 return -ENOENT;
244
245 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
246 pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
247 expr[0].atom, nexpr);
248 return -ENOTSUP;
249 }
250 *offs = (Dwarf_Word)expr[0].number;
251 }
252 return 0;
253}
254
016f262e
MH
255/* Return values for die_find callbacks */
256enum {
257 DIE_FIND_CB_FOUND = 0, /* End of Search */
258 DIE_FIND_CB_CHILD = 1, /* Search only children */
259 DIE_FIND_CB_SIBLING = 2, /* Search only siblings */
260 DIE_FIND_CB_CONTINUE = 3, /* Search children and siblings */
261};
262
263/* Search a child die */
264static Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
265 int (*callback)(Dwarf_Die *, void *),
266 void *data, Dwarf_Die *die_mem)
267{
268 Dwarf_Die child_die;
269 int ret;
270
271 ret = dwarf_child(rt_die, die_mem);
272 if (ret != 0)
273 return NULL;
274
275 do {
276 ret = callback(die_mem, data);
277 if (ret == DIE_FIND_CB_FOUND)
278 return die_mem;
279
280 if ((ret & DIE_FIND_CB_CHILD) &&
281 die_find_child(die_mem, callback, data, &child_die)) {
282 memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
283 return die_mem;
284 }
285 } while ((ret & DIE_FIND_CB_SIBLING) &&
286 dwarf_siblingof(die_mem, die_mem) == 0);
287
288 return NULL;
289}
290
804b3606
MH
291struct __addr_die_search_param {
292 Dwarf_Addr addr;
293 Dwarf_Die *die_mem;
294};
295
296static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
631c9def 297{
804b3606 298 struct __addr_die_search_param *ad = data;
631c9def 299
804b3606
MH
300 if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
301 dwarf_haspc(fn_die, ad->addr)) {
302 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
303 return DWARF_CB_ABORT;
304 }
305 return DWARF_CB_OK;
306}
631c9def 307
804b3606 308/* Search a real subprogram including this line, */
95a3e4c4
MH
309static Dwarf_Die *die_find_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr,
310 Dwarf_Die *die_mem)
804b3606
MH
311{
312 struct __addr_die_search_param ad;
313 ad.addr = addr;
314 ad.die_mem = die_mem;
315 /* dwarf_getscopes can't find subprogram. */
316 if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
317 return NULL;
318 else
319 return die_mem;
631c9def
MH
320}
321
016f262e
MH
322/* die_find callback for inline function search */
323static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
161a26b0 324{
016f262e 325 Dwarf_Addr *addr = data;
161a26b0 326
016f262e
MH
327 if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
328 dwarf_haspc(die_mem, *addr))
329 return DIE_FIND_CB_FOUND;
161a26b0 330
016f262e 331 return DIE_FIND_CB_CONTINUE;
161a26b0
MH
332}
333
016f262e
MH
334/* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */
335static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
336 Dwarf_Die *die_mem)
4ea42b18 337{
016f262e 338 return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
4ea42b18
MH
339}
340
378eeaad
MH
341struct __find_variable_param {
342 const char *name;
343 Dwarf_Addr addr;
344};
345
016f262e 346static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
4ea42b18 347{
378eeaad 348 struct __find_variable_param *fvp = data;
016f262e 349 int tag;
4ea42b18 350
016f262e
MH
351 tag = dwarf_tag(die_mem);
352 if ((tag == DW_TAG_formal_parameter ||
353 tag == DW_TAG_variable) &&
378eeaad 354 die_compare_name(die_mem, fvp->name))
016f262e
MH
355 return DIE_FIND_CB_FOUND;
356
378eeaad
MH
357 if (dwarf_haspc(die_mem, fvp->addr))
358 return DIE_FIND_CB_CONTINUE;
359 else
360 return DIE_FIND_CB_SIBLING;
4ea42b18
MH
361}
362
378eeaad
MH
363/* Find a variable called 'name' at given address */
364static Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
365 Dwarf_Addr addr, Dwarf_Die *die_mem)
4ea42b18 366{
378eeaad
MH
367 struct __find_variable_param fvp = { .name = name, .addr = addr};
368
369 return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
016f262e 370 die_mem);
4ea42b18
MH
371}
372
7df2f329
MH
373static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
374{
375 const char *name = data;
376
377 if ((dwarf_tag(die_mem) == DW_TAG_member) &&
82175633 378 die_compare_name(die_mem, name))
7df2f329
MH
379 return DIE_FIND_CB_FOUND;
380
381 return DIE_FIND_CB_SIBLING;
382}
383
384/* Find a member called 'name' */
385static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
386 Dwarf_Die *die_mem)
387{
388 return die_find_child(st_die, __die_find_member_cb, (void *)name,
389 die_mem);
390}
391
cf6eb489
MH
392/* Get the name of given variable DIE */
393static int die_get_typename(Dwarf_Die *vr_die, char *buf, int len)
394{
395 Dwarf_Die type;
396 int tag, ret, ret2;
397 const char *tmp = "";
398
399 if (__die_get_real_type(vr_die, &type) == NULL)
400 return -ENOENT;
401
402 tag = dwarf_tag(&type);
403 if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
404 tmp = "*";
405 else if (tag == DW_TAG_subroutine_type) {
406 /* Function pointer */
407 ret = snprintf(buf, len, "(function_type)");
408 return (ret >= len) ? -E2BIG : ret;
409 } else {
410 if (!dwarf_diename(&type))
411 return -ENOENT;
412 if (tag == DW_TAG_union_type)
413 tmp = "union ";
414 else if (tag == DW_TAG_structure_type)
415 tmp = "struct ";
416 /* Write a base name */
417 ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type));
418 return (ret >= len) ? -E2BIG : ret;
419 }
420 ret = die_get_typename(&type, buf, len);
421 if (ret > 0) {
422 ret2 = snprintf(buf + ret, len - ret, "%s", tmp);
423 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
424 }
425 return ret;
426}
427
428/* Get the name and type of given variable DIE, stored as "type\tname" */
429static int die_get_varname(Dwarf_Die *vr_die, char *buf, int len)
430{
431 int ret, ret2;
432
433 ret = die_get_typename(vr_die, buf, len);
434 if (ret < 0) {
435 pr_debug("Failed to get type, make it unknown.\n");
436 ret = snprintf(buf, len, "(unknown_type)");
437 }
438 if (ret > 0) {
439 ret2 = snprintf(buf + ret, len - ret, "\t%s",
440 dwarf_diename(vr_die));
441 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
442 }
443 return ret;
444}
445
4ea42b18
MH
446/*
447 * Probe finder related functions
448 */
449
0e60836b 450static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
b7dcb857 451{
0e60836b
SD
452 struct probe_trace_arg_ref *ref;
453 ref = zalloc(sizeof(struct probe_trace_arg_ref));
b7dcb857
MH
454 if (ref != NULL)
455 ref->offset = offs;
456 return ref;
457}
458
cf6eb489
MH
459/*
460 * Convert a location into trace_arg.
461 * If tvar == NULL, this just checks variable can be converted.
462 */
463static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
464 Dwarf_Op *fb_ops,
465 struct probe_trace_arg *tvar)
4ea42b18 466{
b7dcb857
MH
467 Dwarf_Attribute attr;
468 Dwarf_Op *op;
469 size_t nops;
804b3606
MH
470 unsigned int regn;
471 Dwarf_Word offs = 0;
4235b045 472 bool ref = false;
4ea42b18 473 const char *regs;
b7dcb857
MH
474 int ret;
475
632941c4
MH
476 if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
477 goto static_var;
478
b7dcb857
MH
479 /* TODO: handle more than 1 exprs */
480 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL ||
cf6eb489 481 dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0 ||
b7dcb857
MH
482 nops == 0) {
483 /* TODO: Support const_value */
b7dcb857
MH
484 return -ENOENT;
485 }
486
487 if (op->atom == DW_OP_addr) {
632941c4 488static_var:
cf6eb489
MH
489 if (!tvar)
490 return 0;
b7dcb857
MH
491 /* Static variables on memory (not stack), make @varname */
492 ret = strlen(dwarf_diename(vr_die));
493 tvar->value = zalloc(ret + 2);
494 if (tvar->value == NULL)
495 return -ENOMEM;
496 snprintf(tvar->value, ret + 2, "@%s", dwarf_diename(vr_die));
497 tvar->ref = alloc_trace_arg_ref((long)offs);
498 if (tvar->ref == NULL)
499 return -ENOMEM;
500 return 0;
501 }
4ea42b18 502
4ea42b18 503 /* If this is based on frame buffer, set the offset */
804b3606 504 if (op->atom == DW_OP_fbreg) {
cf6eb489 505 if (fb_ops == NULL)
b55a87ad 506 return -ENOTSUP;
4235b045 507 ref = true;
804b3606 508 offs = op->number;
cf6eb489 509 op = &fb_ops[0];
804b3606 510 }
4ea42b18 511
804b3606
MH
512 if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
513 regn = op->atom - DW_OP_breg0;
514 offs += op->number;
4235b045 515 ref = true;
804b3606
MH
516 } else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) {
517 regn = op->atom - DW_OP_reg0;
518 } else if (op->atom == DW_OP_bregx) {
519 regn = op->number;
520 offs += op->number2;
4235b045 521 ref = true;
804b3606
MH
522 } else if (op->atom == DW_OP_regx) {
523 regn = op->number;
b55a87ad 524 } else {
cf6eb489 525 pr_debug("DW_OP %x is not supported.\n", op->atom);
b55a87ad
MH
526 return -ENOTSUP;
527 }
4ea42b18 528
cf6eb489
MH
529 if (!tvar)
530 return 0;
531
4ea42b18 532 regs = get_arch_regstr(regn);
b55a87ad 533 if (!regs) {
cf6eb489
MH
534 /* This should be a bug in DWARF or this tool */
535 pr_warning("Mapping for DWARF register number %u "
536 "missing on this architecture.", regn);
b55a87ad
MH
537 return -ERANGE;
538 }
4ea42b18 539
02b95dad
MH
540 tvar->value = strdup(regs);
541 if (tvar->value == NULL)
542 return -ENOMEM;
543
4235b045 544 if (ref) {
b7dcb857 545 tvar->ref = alloc_trace_arg_ref((long)offs);
e334016f
MH
546 if (tvar->ref == NULL)
547 return -ENOMEM;
4235b045 548 }
b55a87ad 549 return 0;
4ea42b18
MH
550}
551
b55a87ad 552static int convert_variable_type(Dwarf_Die *vr_die,
0e60836b 553 struct probe_trace_arg *tvar,
73317b95 554 const char *cast)
4984912e 555{
0e60836b 556 struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
4984912e
MH
557 Dwarf_Die type;
558 char buf[16];
559 int ret;
560
73317b95
MH
561 /* TODO: check all types */
562 if (cast && strcmp(cast, "string") != 0) {
563 /* Non string type is OK */
564 tvar->type = strdup(cast);
565 return (tvar->type == NULL) ? -ENOMEM : 0;
566 }
567
b55a87ad
MH
568 if (die_get_real_type(vr_die, &type) == NULL) {
569 pr_warning("Failed to get a type information of %s.\n",
570 dwarf_diename(vr_die));
571 return -ENOENT;
572 }
4984912e 573
b2a3c12b
MH
574 pr_debug("%s type is %s.\n",
575 dwarf_diename(vr_die), dwarf_diename(&type));
576
73317b95
MH
577 if (cast && strcmp(cast, "string") == 0) { /* String type */
578 ret = dwarf_tag(&type);
579 if (ret != DW_TAG_pointer_type &&
580 ret != DW_TAG_array_type) {
581 pr_warning("Failed to cast into string: "
582 "%s(%s) is not a pointer nor array.",
583 dwarf_diename(vr_die), dwarf_diename(&type));
584 return -EINVAL;
585 }
586 if (ret == DW_TAG_pointer_type) {
587 if (die_get_real_type(&type, &type) == NULL) {
588 pr_warning("Failed to get a type information.");
589 return -ENOENT;
590 }
591 while (*ref_ptr)
592 ref_ptr = &(*ref_ptr)->next;
593 /* Add new reference with offset +0 */
0e60836b 594 *ref_ptr = zalloc(sizeof(struct probe_trace_arg_ref));
73317b95
MH
595 if (*ref_ptr == NULL) {
596 pr_warning("Out of memory error\n");
597 return -ENOMEM;
598 }
599 }
82175633
MH
600 if (!die_compare_name(&type, "char") &&
601 !die_compare_name(&type, "unsigned char")) {
73317b95
MH
602 pr_warning("Failed to cast into string: "
603 "%s is not (unsigned) char *.",
604 dwarf_diename(vr_die));
605 return -EINVAL;
606 }
607 tvar->type = strdup(cast);
608 return (tvar->type == NULL) ? -ENOMEM : 0;
609 }
610
4984912e
MH
611 ret = die_get_byte_size(&type) * 8;
612 if (ret) {
613 /* Check the bitwidth */
614 if (ret > MAX_BASIC_TYPE_BITS) {
b55a87ad
MH
615 pr_info("%s exceeds max-bitwidth."
616 " Cut down to %d bits.\n",
617 dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
4984912e
MH
618 ret = MAX_BASIC_TYPE_BITS;
619 }
620
621 ret = snprintf(buf, 16, "%c%d",
622 die_is_signed_type(&type) ? 's' : 'u', ret);
b55a87ad
MH
623 if (ret < 0 || ret >= 16) {
624 if (ret >= 16)
625 ret = -E2BIG;
626 pr_warning("Failed to convert variable type: %s\n",
627 strerror(-ret));
628 return ret;
629 }
73317b95
MH
630 tvar->type = strdup(buf);
631 if (tvar->type == NULL)
02b95dad 632 return -ENOMEM;
4984912e 633 }
b55a87ad 634 return 0;
4984912e
MH
635}
636
b55a87ad 637static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
7df2f329 638 struct perf_probe_arg_field *field,
0e60836b 639 struct probe_trace_arg_ref **ref_ptr,
4984912e 640 Dwarf_Die *die_mem)
7df2f329 641{
0e60836b 642 struct probe_trace_arg_ref *ref = *ref_ptr;
7df2f329
MH
643 Dwarf_Die type;
644 Dwarf_Word offs;
b2a3c12b 645 int ret, tag;
7df2f329
MH
646
647 pr_debug("converting %s in %s\n", field->name, varname);
b55a87ad
MH
648 if (die_get_real_type(vr_die, &type) == NULL) {
649 pr_warning("Failed to get the type of %s.\n", varname);
650 return -ENOENT;
651 }
b2a3c12b
MH
652 pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type));
653 tag = dwarf_tag(&type);
654
655 if (field->name[0] == '[' &&
656 (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) {
657 if (field->next)
658 /* Save original type for next field */
659 memcpy(die_mem, &type, sizeof(*die_mem));
660 /* Get the type of this array */
661 if (die_get_real_type(&type, &type) == NULL) {
662 pr_warning("Failed to get the type of %s.\n", varname);
663 return -ENOENT;
664 }
665 pr_debug2("Array real type: (%x)\n",
666 (unsigned)dwarf_dieoffset(&type));
667 if (tag == DW_TAG_pointer_type) {
0e60836b 668 ref = zalloc(sizeof(struct probe_trace_arg_ref));
b2a3c12b
MH
669 if (ref == NULL)
670 return -ENOMEM;
671 if (*ref_ptr)
672 (*ref_ptr)->next = ref;
673 else
674 *ref_ptr = ref;
675 }
676 ref->offset += die_get_byte_size(&type) * field->index;
677 if (!field->next)
678 /* Save vr_die for converting types */
679 memcpy(die_mem, vr_die, sizeof(*die_mem));
680 goto next;
681 } else if (tag == DW_TAG_pointer_type) {
682 /* Check the pointer and dereference */
b55a87ad
MH
683 if (!field->ref) {
684 pr_err("Semantic error: %s must be referred by '->'\n",
685 field->name);
686 return -EINVAL;
687 }
7df2f329 688 /* Get the type pointed by this pointer */
b55a87ad
MH
689 if (die_get_real_type(&type, &type) == NULL) {
690 pr_warning("Failed to get the type of %s.\n", varname);
691 return -ENOENT;
692 }
12e5a7ae 693 /* Verify it is a data structure */
b55a87ad
MH
694 if (dwarf_tag(&type) != DW_TAG_structure_type) {
695 pr_warning("%s is not a data structure.\n", varname);
696 return -EINVAL;
697 }
12e5a7ae 698
0e60836b 699 ref = zalloc(sizeof(struct probe_trace_arg_ref));
e334016f
MH
700 if (ref == NULL)
701 return -ENOMEM;
7df2f329
MH
702 if (*ref_ptr)
703 (*ref_ptr)->next = ref;
704 else
705 *ref_ptr = ref;
706 } else {
12e5a7ae 707 /* Verify it is a data structure */
b2a3c12b 708 if (tag != DW_TAG_structure_type) {
b55a87ad
MH
709 pr_warning("%s is not a data structure.\n", varname);
710 return -EINVAL;
711 }
b2a3c12b
MH
712 if (field->name[0] == '[') {
713 pr_err("Semantic error: %s is not a pointor nor array.",
714 varname);
715 return -EINVAL;
716 }
b55a87ad
MH
717 if (field->ref) {
718 pr_err("Semantic error: %s must be referred by '.'\n",
719 field->name);
720 return -EINVAL;
721 }
722 if (!ref) {
723 pr_warning("Structure on a register is not "
724 "supported yet.\n");
725 return -ENOTSUP;
726 }
7df2f329
MH
727 }
728
b55a87ad
MH
729 if (die_find_member(&type, field->name, die_mem) == NULL) {
730 pr_warning("%s(tyep:%s) has no member %s.\n", varname,
731 dwarf_diename(&type), field->name);
732 return -EINVAL;
733 }
7df2f329
MH
734
735 /* Get the offset of the field */
de1439d8
MH
736 ret = die_get_data_member_location(die_mem, &offs);
737 if (ret < 0) {
b55a87ad 738 pr_warning("Failed to get the offset of %s.\n", field->name);
de1439d8 739 return ret;
b55a87ad 740 }
7df2f329
MH
741 ref->offset += (long)offs;
742
b2a3c12b 743next:
7df2f329
MH
744 /* Converting next field */
745 if (field->next)
b55a87ad 746 return convert_variable_fields(die_mem, field->name,
de1439d8 747 field->next, &ref, die_mem);
b55a87ad
MH
748 else
749 return 0;
7df2f329
MH
750}
751
4ea42b18 752/* Show a variables in kprobe event format */
b55a87ad 753static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
4ea42b18 754{
4984912e 755 Dwarf_Die die_mem;
4ea42b18
MH
756 int ret;
757
b7dcb857
MH
758 pr_debug("Converting variable %s into trace event.\n",
759 dwarf_diename(vr_die));
804b3606 760
cf6eb489
MH
761 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
762 pf->tvar);
763 if (ret == -ENOENT)
764 pr_err("Failed to find the location of %s at this address.\n"
765 " Perhaps, it has been optimized out.\n", pf->pvar->var);
766 else if (ret == -ENOTSUP)
767 pr_err("Sorry, we don't support this variable location yet.\n");
768 else if (pf->pvar->field) {
b55a87ad
MH
769 ret = convert_variable_fields(vr_die, pf->pvar->var,
770 pf->pvar->field, &pf->tvar->ref,
771 &die_mem);
4984912e
MH
772 vr_die = &die_mem;
773 }
73317b95
MH
774 if (ret == 0)
775 ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
804b3606 776 /* *expr will be cached in libdw. Don't free it. */
b55a87ad 777 return ret;
4ea42b18
MH
778}
779
4ea42b18 780/* Find a variable in a subprogram die */
b55a87ad 781static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
4ea42b18 782{
b7dcb857 783 Dwarf_Die vr_die, *scopes;
11a1ca35 784 char buf[32], *ptr;
b7dcb857 785 int ret, nscopes;
4ea42b18 786
367e94c1
MH
787 if (!is_c_varname(pf->pvar->var)) {
788 /* Copy raw parameters */
789 pf->tvar->value = strdup(pf->pvar->var);
790 if (pf->tvar->value == NULL)
791 return -ENOMEM;
792 if (pf->pvar->type) {
793 pf->tvar->type = strdup(pf->pvar->type);
794 if (pf->tvar->type == NULL)
795 return -ENOMEM;
796 }
797 if (pf->pvar->name) {
798 pf->tvar->name = strdup(pf->pvar->name);
799 if (pf->tvar->name == NULL)
800 return -ENOMEM;
801 } else
802 pf->tvar->name = NULL;
803 return 0;
804 }
805
48481938 806 if (pf->pvar->name)
02b95dad 807 pf->tvar->name = strdup(pf->pvar->name);
48481938 808 else {
02b95dad
MH
809 ret = synthesize_perf_probe_arg(pf->pvar, buf, 32);
810 if (ret < 0)
811 return ret;
11a1ca35
MH
812 ptr = strchr(buf, ':'); /* Change type separator to _ */
813 if (ptr)
814 *ptr = '_';
02b95dad 815 pf->tvar->name = strdup(buf);
48481938 816 }
02b95dad
MH
817 if (pf->tvar->name == NULL)
818 return -ENOMEM;
48481938 819
b55a87ad
MH
820 pr_debug("Searching '%s' variable in context.\n",
821 pf->pvar->var);
822 /* Search child die for local variables and parameters. */
378eeaad 823 if (die_find_variable_at(sp_die, pf->pvar->var, pf->addr, &vr_die))
b7dcb857
MH
824 ret = convert_variable(&vr_die, pf);
825 else {
826 /* Search upper class */
827 nscopes = dwarf_getscopes_die(sp_die, &scopes);
632941c4
MH
828 while (nscopes-- > 1) {
829 pr_debug("Searching variables in %s\n",
830 dwarf_diename(&scopes[nscopes]));
831 /* We should check this scope, so give dummy address */
832 if (die_find_variable_at(&scopes[nscopes],
833 pf->pvar->var, 0,
834 &vr_die)) {
b7dcb857 835 ret = convert_variable(&vr_die, pf);
632941c4
MH
836 goto found;
837 }
838 }
839 if (scopes)
b7dcb857 840 free(scopes);
632941c4 841 ret = -ENOENT;
b7dcb857 842 }
632941c4 843found:
b7dcb857 844 if (ret < 0)
b55a87ad
MH
845 pr_warning("Failed to find '%s' in this function.\n",
846 pf->pvar->var);
b7dcb857 847 return ret;
4ea42b18
MH
848}
849
cf6eb489
MH
850/* Convert subprogram DIE to trace point */
851static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
852 bool retprobe, struct probe_trace_point *tp)
4ea42b18 853{
e92b85e1 854 Dwarf_Addr eaddr;
804b3606 855 const char *name;
e92b85e1 856
4235b045 857 /* Copy the name of probe point */
804b3606
MH
858 name = dwarf_diename(sp_die);
859 if (name) {
b55a87ad
MH
860 if (dwarf_entrypc(sp_die, &eaddr) != 0) {
861 pr_warning("Failed to get entry pc of %s\n",
862 dwarf_diename(sp_die));
863 return -ENOENT;
864 }
cf6eb489
MH
865 tp->symbol = strdup(name);
866 if (tp->symbol == NULL)
02b95dad 867 return -ENOMEM;
cf6eb489 868 tp->offset = (unsigned long)(paddr - eaddr);
4235b045 869 } else
4ea42b18 870 /* This function has no name. */
cf6eb489 871 tp->offset = (unsigned long)paddr;
4235b045 872
04ddd04b 873 /* Return probe must be on the head of a subprogram */
cf6eb489
MH
874 if (retprobe) {
875 if (eaddr != paddr) {
04ddd04b
MH
876 pr_warning("Return probe must be on the head of"
877 " a real function\n");
878 return -EINVAL;
879 }
cf6eb489 880 tp->retprobe = true;
04ddd04b
MH
881 }
882
cf6eb489
MH
883 return 0;
884}
885
886/* Call probe_finder callback with real subprogram DIE */
887static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
888{
889 Dwarf_Die die_mem;
890 Dwarf_Attribute fb_attr;
891 size_t nops;
892 int ret;
893
894 /* If no real subprogram, find a real one */
895 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
896 sp_die = die_find_real_subprogram(&pf->cu_die,
897 pf->addr, &die_mem);
898 if (!sp_die) {
899 pr_warning("Failed to find probe point in any "
900 "functions.\n");
901 return -ENOENT;
902 }
903 }
4ea42b18 904
804b3606
MH
905 /* Get the frame base attribute/ops */
906 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
d0cb4260 907 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
a34a9854 908 if (ret <= 0 || nops == 0) {
804b3606 909 pf->fb_ops = NULL;
7752f1b0 910#if _ELFUTILS_PREREQ(0, 142)
a34a9854
MH
911 } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
912 pf->cfi != NULL) {
913 Dwarf_Frame *frame;
b55a87ad
MH
914 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
915 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
916 pr_warning("Failed to get CFA on 0x%jx\n",
917 (uintmax_t)pf->addr);
918 return -ENOENT;
919 }
7752f1b0 920#endif
a34a9854 921 }
804b3606 922
cf6eb489
MH
923 /* Call finder's callback handler */
924 ret = pf->callback(sp_die, pf);
804b3606
MH
925
926 /* *pf->fb_ops will be cached in libdw. Don't free it. */
927 pf->fb_ops = NULL;
cf6eb489
MH
928
929 return ret;
4ea42b18
MH
930}
931
4ea42b18 932/* Find probe point from its line number */
b55a87ad 933static int find_probe_point_by_line(struct probe_finder *pf)
4ea42b18 934{
804b3606
MH
935 Dwarf_Lines *lines;
936 Dwarf_Line *line;
937 size_t nlines, i;
e92b85e1 938 Dwarf_Addr addr;
804b3606 939 int lineno;
b55a87ad 940 int ret = 0;
4ea42b18 941
b55a87ad
MH
942 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
943 pr_warning("No source lines found in this CU.\n");
944 return -ENOENT;
945 }
4ea42b18 946
b55a87ad 947 for (i = 0; i < nlines && ret == 0; i++) {
804b3606 948 line = dwarf_onesrcline(lines, i);
b55a87ad
MH
949 if (dwarf_lineno(line, &lineno) != 0 ||
950 lineno != pf->lno)
4ea42b18
MH
951 continue;
952
804b3606
MH
953 /* TODO: Get fileno from line, but how? */
954 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
955 continue;
b0ef0732 956
b55a87ad
MH
957 if (dwarf_lineaddr(line, &addr) != 0) {
958 pr_warning("Failed to get the address of the line.\n");
959 return -ENOENT;
960 }
804b3606
MH
961 pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
962 (int)i, lineno, (uintmax_t)addr);
4ea42b18 963 pf->addr = addr;
804b3606 964
cf6eb489 965 ret = call_probe_finder(NULL, pf);
4ea42b18
MH
966 /* Continuing, because target line might be inlined. */
967 }
b55a87ad 968 return ret;
4ea42b18
MH
969}
970
2a9c8c36
MH
971/* Find lines which match lazy pattern */
972static int find_lazy_match_lines(struct list_head *head,
973 const char *fname, const char *pat)
974{
975 char *fbuf, *p1, *p2;
b448c4b6 976 int fd, line, nlines = -1;
2a9c8c36
MH
977 struct stat st;
978
979 fd = open(fname, O_RDONLY);
b55a87ad
MH
980 if (fd < 0) {
981 pr_warning("Failed to open %s: %s\n", fname, strerror(-fd));
b448c4b6 982 return -errno;
b55a87ad
MH
983 }
984
b448c4b6 985 if (fstat(fd, &st) < 0) {
b55a87ad
MH
986 pr_warning("Failed to get the size of %s: %s\n",
987 fname, strerror(errno));
b448c4b6
ACM
988 nlines = -errno;
989 goto out_close;
b55a87ad 990 }
b448c4b6
ACM
991
992 nlines = -ENOMEM;
993 fbuf = malloc(st.st_size + 2);
994 if (fbuf == NULL)
995 goto out_close;
996 if (read(fd, fbuf, st.st_size) < 0) {
b55a87ad 997 pr_warning("Failed to read %s: %s\n", fname, strerror(errno));
b448c4b6
ACM
998 nlines = -errno;
999 goto out_free_fbuf;
b55a87ad 1000 }
2a9c8c36
MH
1001 fbuf[st.st_size] = '\n'; /* Dummy line */
1002 fbuf[st.st_size + 1] = '\0';
1003 p1 = fbuf;
1004 line = 1;
b448c4b6 1005 nlines = 0;
2a9c8c36
MH
1006 while ((p2 = strchr(p1, '\n')) != NULL) {
1007 *p2 = '\0';
1008 if (strlazymatch(p1, pat)) {
1009 line_list__add_line(head, line);
1010 nlines++;
1011 }
1012 line++;
1013 p1 = p2 + 1;
1014 }
b448c4b6 1015out_free_fbuf:
2a9c8c36 1016 free(fbuf);
b448c4b6
ACM
1017out_close:
1018 close(fd);
2a9c8c36
MH
1019 return nlines;
1020}
1021
1022/* Find probe points from lazy pattern */
b55a87ad 1023static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
2a9c8c36
MH
1024{
1025 Dwarf_Lines *lines;
1026 Dwarf_Line *line;
1027 size_t nlines, i;
1028 Dwarf_Addr addr;
1029 Dwarf_Die die_mem;
1030 int lineno;
b55a87ad 1031 int ret = 0;
2a9c8c36
MH
1032
1033 if (list_empty(&pf->lcache)) {
1034 /* Matching lazy line pattern */
1035 ret = find_lazy_match_lines(&pf->lcache, pf->fname,
4235b045 1036 pf->pev->point.lazy_line);
b55a87ad
MH
1037 if (ret == 0) {
1038 pr_debug("No matched lines found in %s.\n", pf->fname);
1039 return 0;
1040 } else if (ret < 0)
1041 return ret;
2a9c8c36
MH
1042 }
1043
b55a87ad
MH
1044 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
1045 pr_warning("No source lines found in this CU.\n");
1046 return -ENOENT;
1047 }
1048
1049 for (i = 0; i < nlines && ret >= 0; i++) {
2a9c8c36
MH
1050 line = dwarf_onesrcline(lines, i);
1051
b55a87ad
MH
1052 if (dwarf_lineno(line, &lineno) != 0 ||
1053 !line_list__has_line(&pf->lcache, lineno))
2a9c8c36
MH
1054 continue;
1055
1056 /* TODO: Get fileno from line, but how? */
1057 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
1058 continue;
1059
b55a87ad
MH
1060 if (dwarf_lineaddr(line, &addr) != 0) {
1061 pr_debug("Failed to get the address of line %d.\n",
1062 lineno);
1063 continue;
1064 }
2a9c8c36
MH
1065 if (sp_die) {
1066 /* Address filtering 1: does sp_die include addr? */
1067 if (!dwarf_haspc(sp_die, addr))
1068 continue;
1069 /* Address filtering 2: No child include addr? */
95a3e4c4 1070 if (die_find_inlinefunc(sp_die, addr, &die_mem))
2a9c8c36
MH
1071 continue;
1072 }
1073
1074 pr_debug("Probe line found: line[%d]:%d addr:0x%llx\n",
1075 (int)i, lineno, (unsigned long long)addr);
1076 pf->addr = addr;
1077
cf6eb489 1078 ret = call_probe_finder(sp_die, pf);
2a9c8c36
MH
1079 /* Continuing, because target line might be inlined. */
1080 }
1081 /* TODO: deallocate lines, but how? */
b55a87ad 1082 return ret;
2a9c8c36
MH
1083}
1084
b55a87ad
MH
1085/* Callback parameter with return value */
1086struct dwarf_callback_param {
1087 void *data;
1088 int retval;
1089};
1090
e92b85e1
MH
1091static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
1092{
b55a87ad
MH
1093 struct dwarf_callback_param *param = data;
1094 struct probe_finder *pf = param->data;
4235b045 1095 struct perf_probe_point *pp = &pf->pev->point;
b55a87ad 1096 Dwarf_Addr addr;
e92b85e1 1097
2a9c8c36 1098 if (pp->lazy_line)
b55a87ad 1099 param->retval = find_probe_point_lazy(in_die, pf);
2a9c8c36
MH
1100 else {
1101 /* Get probe address */
b55a87ad
MH
1102 if (dwarf_entrypc(in_die, &addr) != 0) {
1103 pr_warning("Failed to get entry pc of %s.\n",
1104 dwarf_diename(in_die));
1105 param->retval = -ENOENT;
1106 return DWARF_CB_ABORT;
1107 }
1108 pf->addr = addr;
2a9c8c36
MH
1109 pf->addr += pp->offset;
1110 pr_debug("found inline addr: 0x%jx\n",
1111 (uintmax_t)pf->addr);
1112
cf6eb489 1113 param->retval = call_probe_finder(in_die, pf);
5d1ee041
MH
1114 if (param->retval < 0)
1115 return DWARF_CB_ABORT;
2a9c8c36 1116 }
e92b85e1 1117
e92b85e1
MH
1118 return DWARF_CB_OK;
1119}
804b3606 1120
4ea42b18 1121/* Search function from function name */
e92b85e1 1122static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
4ea42b18 1123{
b55a87ad
MH
1124 struct dwarf_callback_param *param = data;
1125 struct probe_finder *pf = param->data;
4235b045 1126 struct perf_probe_point *pp = &pf->pev->point;
4ea42b18 1127
e92b85e1
MH
1128 /* Check tag and diename */
1129 if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
82175633 1130 !die_compare_name(sp_die, pp->function))
b55a87ad 1131 return DWARF_CB_OK;
e92b85e1 1132
2a9c8c36 1133 pf->fname = dwarf_decl_file(sp_die);
e92b85e1 1134 if (pp->line) { /* Function relative line */
e92b85e1
MH
1135 dwarf_decl_line(sp_die, &pf->lno);
1136 pf->lno += pp->line;
b55a87ad 1137 param->retval = find_probe_point_by_line(pf);
e92b85e1
MH
1138 } else if (!dwarf_func_inline(sp_die)) {
1139 /* Real function */
2a9c8c36 1140 if (pp->lazy_line)
b55a87ad 1141 param->retval = find_probe_point_lazy(sp_die, pf);
2a9c8c36 1142 else {
b55a87ad
MH
1143 if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
1144 pr_warning("Failed to get entry pc of %s.\n",
1145 dwarf_diename(sp_die));
1146 param->retval = -ENOENT;
1147 return DWARF_CB_ABORT;
1148 }
2a9c8c36
MH
1149 pf->addr += pp->offset;
1150 /* TODO: Check the address in this function */
cf6eb489 1151 param->retval = call_probe_finder(sp_die, pf);
2a9c8c36 1152 }
b55a87ad
MH
1153 } else {
1154 struct dwarf_callback_param _param = {.data = (void *)pf,
1155 .retval = 0};
e92b85e1 1156 /* Inlined function: search instances */
b55a87ad
MH
1157 dwarf_func_inline_instances(sp_die, probe_point_inline_cb,
1158 &_param);
1159 param->retval = _param.retval;
1160 }
e92b85e1 1161
b55a87ad 1162 return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
4ea42b18
MH
1163}
1164
b55a87ad 1165static int find_probe_point_by_func(struct probe_finder *pf)
4ea42b18 1166{
b55a87ad
MH
1167 struct dwarf_callback_param _param = {.data = (void *)pf,
1168 .retval = 0};
1169 dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
1170 return _param.retval;
4ea42b18
MH
1171}
1172
cf6eb489
MH
1173/* Find probe points from debuginfo */
1174static int find_probes(int fd, struct probe_finder *pf)
4ea42b18 1175{
cf6eb489 1176 struct perf_probe_point *pp = &pf->pev->point;
804b3606
MH
1177 Dwarf_Off off, noff;
1178 size_t cuhl;
1179 Dwarf_Die *diep;
1180 Dwarf *dbg;
b55a87ad 1181 int ret = 0;
804b3606
MH
1182
1183 dbg = dwarf_begin(fd, DWARF_C_READ);
b55a87ad
MH
1184 if (!dbg) {
1185 pr_warning("No dwarf info found in the vmlinux - "
1186 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1187 return -EBADF;
1188 }
4ea42b18 1189
7752f1b0 1190#if _ELFUTILS_PREREQ(0, 142)
a34a9854 1191 /* Get the call frame information from this dwarf */
cf6eb489 1192 pf->cfi = dwarf_getcfi(dbg);
7752f1b0 1193#endif
a34a9854 1194
804b3606 1195 off = 0;
cf6eb489 1196 line_list__init(&pf->lcache);
804b3606 1197 /* Loop on CUs (Compilation Unit) */
b55a87ad
MH
1198 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) &&
1199 ret >= 0) {
4ea42b18 1200 /* Get the DIE(Debugging Information Entry) of this CU */
cf6eb489 1201 diep = dwarf_offdie(dbg, off + cuhl, &pf->cu_die);
804b3606
MH
1202 if (!diep)
1203 continue;
4ea42b18
MH
1204
1205 /* Check if target file is included. */
1206 if (pp->file)
cf6eb489 1207 pf->fname = cu_find_realpath(&pf->cu_die, pp->file);
804b3606 1208 else
cf6eb489 1209 pf->fname = NULL;
4ea42b18 1210
cf6eb489 1211 if (!pp->file || pf->fname) {
4ea42b18 1212 if (pp->function)
cf6eb489 1213 ret = find_probe_point_by_func(pf);
2a9c8c36 1214 else if (pp->lazy_line)
cf6eb489 1215 ret = find_probe_point_lazy(NULL, pf);
b0ef0732 1216 else {
cf6eb489
MH
1217 pf->lno = pp->line;
1218 ret = find_probe_point_by_line(pf);
b0ef0732 1219 }
4ea42b18 1220 }
804b3606 1221 off = noff;
4ea42b18 1222 }
cf6eb489 1223 line_list__free(&pf->lcache);
804b3606 1224 dwarf_end(dbg);
4ea42b18 1225
cf6eb489
MH
1226 return ret;
1227}
1228
1229/* Add a found probe point into trace event list */
1230static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf)
1231{
1232 struct trace_event_finder *tf =
1233 container_of(pf, struct trace_event_finder, pf);
1234 struct probe_trace_event *tev;
1235 int ret, i;
1236
1237 /* Check number of tevs */
1238 if (tf->ntevs == tf->max_tevs) {
1239 pr_warning("Too many( > %d) probe point found.\n",
1240 tf->max_tevs);
1241 return -ERANGE;
1242 }
1243 tev = &tf->tevs[tf->ntevs++];
1244
1245 ret = convert_to_trace_point(sp_die, pf->addr, pf->pev->point.retprobe,
1246 &tev->point);
1247 if (ret < 0)
1248 return ret;
1249
1250 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
1251 tev->point.offset);
1252
1253 /* Find each argument */
1254 tev->nargs = pf->pev->nargs;
1255 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
1256 if (tev->args == NULL)
1257 return -ENOMEM;
1258 for (i = 0; i < pf->pev->nargs; i++) {
1259 pf->pvar = &pf->pev->args[i];
1260 pf->tvar = &tev->args[i];
1261 ret = find_variable(sp_die, pf);
1262 if (ret != 0)
1263 return ret;
1264 }
1265
1266 return 0;
1267}
1268
1269/* Find probe_trace_events specified by perf_probe_event from debuginfo */
1270int find_probe_trace_events(int fd, struct perf_probe_event *pev,
1271 struct probe_trace_event **tevs, int max_tevs)
1272{
1273 struct trace_event_finder tf = {
1274 .pf = {.pev = pev, .callback = add_probe_trace_event},
1275 .max_tevs = max_tevs};
1276 int ret;
1277
1278 /* Allocate result tevs array */
1279 *tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs);
1280 if (*tevs == NULL)
1281 return -ENOMEM;
1282
1283 tf.tevs = *tevs;
1284 tf.ntevs = 0;
1285
1286 ret = find_probes(fd, &tf.pf);
1287 if (ret < 0) {
1288 free(*tevs);
1289 *tevs = NULL;
1290 return ret;
1291 }
1292
1293 return (ret < 0) ? ret : tf.ntevs;
1294}
1295
1296#define MAX_VAR_LEN 64
1297
1298/* Collect available variables in this scope */
1299static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1300{
1301 struct available_var_finder *af = data;
1302 struct variable_list *vl;
1303 char buf[MAX_VAR_LEN];
1304 int tag, ret;
1305
1306 vl = &af->vls[af->nvls - 1];
1307
1308 tag = dwarf_tag(die_mem);
1309 if (tag == DW_TAG_formal_parameter ||
1310 tag == DW_TAG_variable) {
1311 ret = convert_variable_location(die_mem, af->pf.addr,
1312 af->pf.fb_ops, NULL);
1313 if (ret == 0) {
1314 ret = die_get_varname(die_mem, buf, MAX_VAR_LEN);
1315 if (ret > 0)
1316 strlist__add(vl->vars, buf);
1317 }
1318 }
1319
1320 if (dwarf_haspc(die_mem, af->pf.addr))
1321 return DIE_FIND_CB_CONTINUE;
1322 else
1323 return DIE_FIND_CB_SIBLING;
1324}
1325
1326/* Add a found vars into available variables list */
1327static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
1328{
1329 struct available_var_finder *af =
1330 container_of(pf, struct available_var_finder, pf);
1331 struct variable_list *vl;
1332 Dwarf_Die die_mem;
1333 int ret;
1334
1335 /* Check number of tevs */
1336 if (af->nvls == af->max_vls) {
1337 pr_warning("Too many( > %d) probe point found.\n", af->max_vls);
1338 return -ERANGE;
1339 }
1340 vl = &af->vls[af->nvls++];
1341
1342 ret = convert_to_trace_point(sp_die, pf->addr, pf->pev->point.retprobe,
1343 &vl->point);
1344 if (ret < 0)
1345 return ret;
1346
1347 pr_debug("Probe point found: %s+%lu\n", vl->point.symbol,
1348 vl->point.offset);
1349
1350 /* Find local variables */
1351 vl->vars = strlist__new(true, NULL);
1352 if (vl->vars == NULL)
1353 return -ENOMEM;
1354 die_find_child(sp_die, collect_variables_cb, (void *)af, &die_mem);
1355
1356 if (strlist__empty(vl->vars)) {
1357 strlist__delete(vl->vars);
1358 vl->vars = NULL;
1359 }
1360
1361 return ret;
1362}
1363
1364/* Find available variables at given probe point */
1365int find_available_vars_at(int fd, struct perf_probe_event *pev,
1366 struct variable_list **vls, int max_vls)
1367{
1368 struct available_var_finder af = {
1369 .pf = {.pev = pev, .callback = add_available_vars},
1370 .max_vls = max_vls};
1371 int ret;
1372
1373 /* Allocate result vls array */
1374 *vls = zalloc(sizeof(struct variable_list) * max_vls);
1375 if (*vls == NULL)
1376 return -ENOMEM;
1377
1378 af.vls = *vls;
1379 af.nvls = 0;
1380
1381 ret = find_probes(fd, &af.pf);
1382 if (ret < 0) {
1383 /* Free vlist for error */
1384 while (af.nvls--) {
1385 if (af.vls[af.nvls].point.symbol)
1386 free(af.vls[af.nvls].point.symbol);
1387 if (af.vls[af.nvls].vars)
1388 strlist__delete(af.vls[af.nvls].vars);
1389 }
1390 free(af.vls);
1391 *vls = NULL;
1392 return ret;
1393 }
1394
1395 return (ret < 0) ? ret : af.nvls;
4ea42b18
MH
1396}
1397
fb1587d8
MH
1398/* Reverse search */
1399int find_perf_probe_point(int fd, unsigned long addr,
1400 struct perf_probe_point *ppt)
1401{
1402 Dwarf_Die cudie, spdie, indie;
1403 Dwarf *dbg;
1404 Dwarf_Line *line;
1405 Dwarf_Addr laddr, eaddr;
1406 const char *tmp;
1407 int lineno, ret = 0;
b55a87ad 1408 bool found = false;
fb1587d8
MH
1409
1410 dbg = dwarf_begin(fd, DWARF_C_READ);
1411 if (!dbg)
b55a87ad 1412 return -EBADF;
fb1587d8
MH
1413
1414 /* Find cu die */
75ec5a24
MH
1415 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) {
1416 ret = -EINVAL;
1417 goto end;
1418 }
fb1587d8
MH
1419
1420 /* Find a corresponding line */
1421 line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr);
1422 if (line) {
b55a87ad
MH
1423 if (dwarf_lineaddr(line, &laddr) == 0 &&
1424 (Dwarf_Addr)addr == laddr &&
1425 dwarf_lineno(line, &lineno) == 0) {
fb1587d8 1426 tmp = dwarf_linesrc(line, NULL, NULL);
b55a87ad
MH
1427 if (tmp) {
1428 ppt->line = lineno;
02b95dad
MH
1429 ppt->file = strdup(tmp);
1430 if (ppt->file == NULL) {
1431 ret = -ENOMEM;
1432 goto end;
1433 }
b55a87ad
MH
1434 found = true;
1435 }
fb1587d8
MH
1436 }
1437 }
1438
1439 /* Find a corresponding function */
1440 if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) {
1441 tmp = dwarf_diename(&spdie);
b55a87ad 1442 if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0)
fb1587d8
MH
1443 goto end;
1444
b55a87ad
MH
1445 if (ppt->line) {
1446 if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
1447 &indie)) {
1448 /* addr in an inline function */
1449 tmp = dwarf_diename(&indie);
1450 if (!tmp)
1451 goto end;
1452 ret = dwarf_decl_line(&indie, &lineno);
1453 } else {
1454 if (eaddr == addr) { /* Function entry */
1455 lineno = ppt->line;
1456 ret = 0;
1457 } else
1458 ret = dwarf_decl_line(&spdie, &lineno);
1459 }
1460 if (ret == 0) {
1461 /* Make a relative line number */
1462 ppt->line -= lineno;
1463 goto found;
1464 }
fb1587d8 1465 }
b55a87ad
MH
1466 /* We don't have a line number, let's use offset */
1467 ppt->offset = addr - (unsigned long)eaddr;
1468found:
02b95dad
MH
1469 ppt->function = strdup(tmp);
1470 if (ppt->function == NULL) {
1471 ret = -ENOMEM;
1472 goto end;
1473 }
b55a87ad 1474 found = true;
fb1587d8
MH
1475 }
1476
1477end:
1478 dwarf_end(dbg);
b55a87ad
MH
1479 if (ret >= 0)
1480 ret = found ? 1 : 0;
fb1587d8
MH
1481 return ret;
1482}
1483
f6c903f5
MH
1484/* Add a line and store the src path */
1485static int line_range_add_line(const char *src, unsigned int lineno,
1486 struct line_range *lr)
1487{
7cf0b79e 1488 /* Copy source path */
f6c903f5 1489 if (!lr->path) {
7cf0b79e
MH
1490 lr->path = strdup(src);
1491 if (lr->path == NULL)
1492 return -ENOMEM;
f6c903f5
MH
1493 }
1494 return line_list__add_line(&lr->line_list, lineno);
1495}
1496
1497/* Search function declaration lines */
1498static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data)
1499{
1500 struct dwarf_callback_param *param = data;
1501 struct line_finder *lf = param->data;
1502 const char *src;
1503 int lineno;
1504
1505 src = dwarf_decl_file(sp_die);
1506 if (src && strtailcmp(src, lf->fname) != 0)
1507 return DWARF_CB_OK;
1508
1509 if (dwarf_decl_line(sp_die, &lineno) != 0 ||
1510 (lf->lno_s > lineno || lf->lno_e < lineno))
1511 return DWARF_CB_OK;
1512
1513 param->retval = line_range_add_line(src, lineno, lf->lr);
5d1ee041
MH
1514 if (param->retval < 0)
1515 return DWARF_CB_ABORT;
f6c903f5
MH
1516 return DWARF_CB_OK;
1517}
1518
1519static int find_line_range_func_decl_lines(struct line_finder *lf)
1520{
1521 struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
1522 dwarf_getfuncs(&lf->cu_die, line_range_funcdecl_cb, &param, 0);
1523 return param.retval;
1524}
fb1587d8 1525
631c9def 1526/* Find line range from its line number */
b55a87ad 1527static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
631c9def 1528{
804b3606
MH
1529 Dwarf_Lines *lines;
1530 Dwarf_Line *line;
1531 size_t nlines, i;
631c9def 1532 Dwarf_Addr addr;
f6c903f5 1533 int lineno, ret = 0;
804b3606 1534 const char *src;
161a26b0 1535 Dwarf_Die die_mem;
631c9def 1536
2a9c8c36 1537 line_list__init(&lf->lr->line_list);
b55a87ad
MH
1538 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
1539 pr_warning("No source lines found in this CU.\n");
1540 return -ENOENT;
1541 }
631c9def 1542
f6c903f5 1543 /* Search probable lines on lines list */
804b3606
MH
1544 for (i = 0; i < nlines; i++) {
1545 line = dwarf_onesrcline(lines, i);
b55a87ad
MH
1546 if (dwarf_lineno(line, &lineno) != 0 ||
1547 (lf->lno_s > lineno || lf->lno_e < lineno))
631c9def
MH
1548 continue;
1549
161a26b0
MH
1550 if (sp_die) {
1551 /* Address filtering 1: does sp_die include addr? */
b55a87ad
MH
1552 if (dwarf_lineaddr(line, &addr) != 0 ||
1553 !dwarf_haspc(sp_die, addr))
161a26b0
MH
1554 continue;
1555
1556 /* Address filtering 2: No child include addr? */
95a3e4c4 1557 if (die_find_inlinefunc(sp_die, addr, &die_mem))
161a26b0
MH
1558 continue;
1559 }
1560
804b3606
MH
1561 /* TODO: Get fileno from line, but how? */
1562 src = dwarf_linesrc(line, NULL, NULL);
1563 if (strtailcmp(src, lf->fname) != 0)
631c9def
MH
1564 continue;
1565
f6c903f5
MH
1566 ret = line_range_add_line(src, lineno, lf->lr);
1567 if (ret < 0)
1568 return ret;
631c9def 1569 }
f6c903f5
MH
1570
1571 /*
1572 * Dwarf lines doesn't include function declarations. We have to
1573 * check functions list or given function.
1574 */
1575 if (sp_die) {
1576 src = dwarf_decl_file(sp_die);
1577 if (src && dwarf_decl_line(sp_die, &lineno) == 0 &&
1578 (lf->lno_s <= lineno && lf->lno_e >= lineno))
1579 ret = line_range_add_line(src, lineno, lf->lr);
1580 } else
1581 ret = find_line_range_func_decl_lines(lf);
1582
804b3606 1583 /* Update status */
f6c903f5
MH
1584 if (ret >= 0)
1585 if (!list_empty(&lf->lr->line_list))
1586 ret = lf->found = 1;
1587 else
1588 ret = 0; /* Lines are not found */
804b3606
MH
1589 else {
1590 free(lf->lr->path);
1591 lf->lr->path = NULL;
1592 }
f6c903f5 1593 return ret;
631c9def
MH
1594}
1595
161a26b0
MH
1596static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
1597{
b55a87ad
MH
1598 struct dwarf_callback_param *param = data;
1599
1600 param->retval = find_line_range_by_line(in_die, param->data);
161a26b0
MH
1601 return DWARF_CB_ABORT; /* No need to find other instances */
1602}
1603
631c9def 1604/* Search function from function name */
e92b85e1 1605static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
631c9def 1606{
b55a87ad
MH
1607 struct dwarf_callback_param *param = data;
1608 struct line_finder *lf = param->data;
631c9def 1609 struct line_range *lr = lf->lr;
631c9def 1610
e92b85e1 1611 if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
82175633 1612 die_compare_name(sp_die, lr->function)) {
e92b85e1
MH
1613 lf->fname = dwarf_decl_file(sp_die);
1614 dwarf_decl_line(sp_die, &lr->offset);
804b3606 1615 pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
631c9def 1616 lf->lno_s = lr->offset + lr->start;
d3b63d7a
MH
1617 if (lf->lno_s < 0) /* Overflow */
1618 lf->lno_s = INT_MAX;
1619 lf->lno_e = lr->offset + lr->end;
1620 if (lf->lno_e < 0) /* Overflow */
804b3606 1621 lf->lno_e = INT_MAX;
d3b63d7a 1622 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
631c9def
MH
1623 lr->start = lf->lno_s;
1624 lr->end = lf->lno_e;
b55a87ad
MH
1625 if (dwarf_func_inline(sp_die)) {
1626 struct dwarf_callback_param _param;
1627 _param.data = (void *)lf;
1628 _param.retval = 0;
161a26b0 1629 dwarf_func_inline_instances(sp_die,
b55a87ad
MH
1630 line_range_inline_cb,
1631 &_param);
1632 param->retval = _param.retval;
1633 } else
1634 param->retval = find_line_range_by_line(sp_die, lf);
1635 return DWARF_CB_ABORT;
631c9def 1636 }
b55a87ad 1637 return DWARF_CB_OK;
631c9def
MH
1638}
1639
b55a87ad 1640static int find_line_range_by_func(struct line_finder *lf)
631c9def 1641{
b55a87ad
MH
1642 struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
1643 dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
1644 return param.retval;
631c9def
MH
1645}
1646
1647int find_line_range(int fd, struct line_range *lr)
1648{
804b3606 1649 struct line_finder lf = {.lr = lr, .found = 0};
b55a87ad 1650 int ret = 0;
804b3606
MH
1651 Dwarf_Off off = 0, noff;
1652 size_t cuhl;
1653 Dwarf_Die *diep;
1654 Dwarf *dbg;
6a330a3c 1655 const char *comp_dir;
804b3606
MH
1656
1657 dbg = dwarf_begin(fd, DWARF_C_READ);
b55a87ad
MH
1658 if (!dbg) {
1659 pr_warning("No dwarf info found in the vmlinux - "
1660 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1661 return -EBADF;
1662 }
631c9def 1663
804b3606 1664 /* Loop on CUs (Compilation Unit) */
b55a87ad
MH
1665 while (!lf.found && ret >= 0) {
1666 if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0)
631c9def
MH
1667 break;
1668
1669 /* Get the DIE(Debugging Information Entry) of this CU */
804b3606
MH
1670 diep = dwarf_offdie(dbg, off + cuhl, &lf.cu_die);
1671 if (!diep)
1672 continue;
631c9def
MH
1673
1674 /* Check if target file is included. */
1675 if (lr->file)
2a9c8c36 1676 lf.fname = cu_find_realpath(&lf.cu_die, lr->file);
804b3606 1677 else
2a9c8c36 1678 lf.fname = 0;
631c9def 1679
2a9c8c36 1680 if (!lr->file || lf.fname) {
631c9def 1681 if (lr->function)
b55a87ad 1682 ret = find_line_range_by_func(&lf);
631c9def
MH
1683 else {
1684 lf.lno_s = lr->start;
d3b63d7a 1685 lf.lno_e = lr->end;
b55a87ad 1686 ret = find_line_range_by_line(NULL, &lf);
631c9def 1687 }
631c9def 1688 }
804b3606 1689 off = noff;
631c9def 1690 }
6a330a3c
MH
1691
1692 /* Store comp_dir */
1693 if (lf.found) {
1694 comp_dir = cu_get_comp_dir(&lf.cu_die);
1695 if (comp_dir) {
1696 lr->comp_dir = strdup(comp_dir);
1697 if (!lr->comp_dir)
1698 ret = -ENOMEM;
1699 }
1700 }
1701
7cf0b79e 1702 pr_debug("path: %s\n", lr->path);
804b3606 1703 dwarf_end(dbg);
b55a87ad
MH
1704
1705 return (ret < 0) ? ret : lf.found;
631c9def
MH
1706}
1707