perf probe: Support global variables
[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
7df2f329
MH
175/* Get type die, but skip qualifiers and typedef */
176static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
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 ||
188 tag == DW_TAG_shared_type ||
189 tag == DW_TAG_typedef);
190
4046b8bb 191 return vr_die;
7df2f329
MH
192}
193
4984912e
MH
194static bool die_is_signed_type(Dwarf_Die *tp_die)
195{
196 Dwarf_Attribute attr;
197 Dwarf_Word ret;
198
199 if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL ||
200 dwarf_formudata(&attr, &ret) != 0)
201 return false;
202
203 return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
204 ret == DW_ATE_signed_fixed);
205}
206
207static int die_get_byte_size(Dwarf_Die *tp_die)
208{
209 Dwarf_Attribute attr;
210 Dwarf_Word ret;
211
212 if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL ||
213 dwarf_formudata(&attr, &ret) != 0)
214 return 0;
215
216 return (int)ret;
217}
218
de1439d8
MH
219/* Get data_member_location offset */
220static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
221{
222 Dwarf_Attribute attr;
223 Dwarf_Op *expr;
224 size_t nexpr;
225 int ret;
226
227 if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
228 return -ENOENT;
229
230 if (dwarf_formudata(&attr, offs) != 0) {
231 /* DW_AT_data_member_location should be DW_OP_plus_uconst */
232 ret = dwarf_getlocation(&attr, &expr, &nexpr);
233 if (ret < 0 || nexpr == 0)
234 return -ENOENT;
235
236 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
237 pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
238 expr[0].atom, nexpr);
239 return -ENOTSUP;
240 }
241 *offs = (Dwarf_Word)expr[0].number;
242 }
243 return 0;
244}
245
016f262e
MH
246/* Return values for die_find callbacks */
247enum {
248 DIE_FIND_CB_FOUND = 0, /* End of Search */
249 DIE_FIND_CB_CHILD = 1, /* Search only children */
250 DIE_FIND_CB_SIBLING = 2, /* Search only siblings */
251 DIE_FIND_CB_CONTINUE = 3, /* Search children and siblings */
252};
253
254/* Search a child die */
255static Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
256 int (*callback)(Dwarf_Die *, void *),
257 void *data, Dwarf_Die *die_mem)
258{
259 Dwarf_Die child_die;
260 int ret;
261
262 ret = dwarf_child(rt_die, die_mem);
263 if (ret != 0)
264 return NULL;
265
266 do {
267 ret = callback(die_mem, data);
268 if (ret == DIE_FIND_CB_FOUND)
269 return die_mem;
270
271 if ((ret & DIE_FIND_CB_CHILD) &&
272 die_find_child(die_mem, callback, data, &child_die)) {
273 memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
274 return die_mem;
275 }
276 } while ((ret & DIE_FIND_CB_SIBLING) &&
277 dwarf_siblingof(die_mem, die_mem) == 0);
278
279 return NULL;
280}
281
804b3606
MH
282struct __addr_die_search_param {
283 Dwarf_Addr addr;
284 Dwarf_Die *die_mem;
285};
286
287static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
631c9def 288{
804b3606 289 struct __addr_die_search_param *ad = data;
631c9def 290
804b3606
MH
291 if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
292 dwarf_haspc(fn_die, ad->addr)) {
293 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
294 return DWARF_CB_ABORT;
295 }
296 return DWARF_CB_OK;
297}
631c9def 298
804b3606 299/* Search a real subprogram including this line, */
95a3e4c4
MH
300static Dwarf_Die *die_find_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr,
301 Dwarf_Die *die_mem)
804b3606
MH
302{
303 struct __addr_die_search_param ad;
304 ad.addr = addr;
305 ad.die_mem = die_mem;
306 /* dwarf_getscopes can't find subprogram. */
307 if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
308 return NULL;
309 else
310 return die_mem;
631c9def
MH
311}
312
016f262e
MH
313/* die_find callback for inline function search */
314static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
161a26b0 315{
016f262e 316 Dwarf_Addr *addr = data;
161a26b0 317
016f262e
MH
318 if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
319 dwarf_haspc(die_mem, *addr))
320 return DIE_FIND_CB_FOUND;
161a26b0 321
016f262e 322 return DIE_FIND_CB_CONTINUE;
161a26b0
MH
323}
324
016f262e
MH
325/* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */
326static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
327 Dwarf_Die *die_mem)
4ea42b18 328{
016f262e 329 return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
4ea42b18
MH
330}
331
378eeaad
MH
332struct __find_variable_param {
333 const char *name;
334 Dwarf_Addr addr;
335};
336
016f262e 337static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
4ea42b18 338{
378eeaad 339 struct __find_variable_param *fvp = data;
016f262e 340 int tag;
4ea42b18 341
016f262e
MH
342 tag = dwarf_tag(die_mem);
343 if ((tag == DW_TAG_formal_parameter ||
344 tag == DW_TAG_variable) &&
378eeaad 345 die_compare_name(die_mem, fvp->name))
016f262e
MH
346 return DIE_FIND_CB_FOUND;
347
378eeaad
MH
348 if (dwarf_haspc(die_mem, fvp->addr))
349 return DIE_FIND_CB_CONTINUE;
350 else
351 return DIE_FIND_CB_SIBLING;
4ea42b18
MH
352}
353
378eeaad
MH
354/* Find a variable called 'name' at given address */
355static Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
356 Dwarf_Addr addr, Dwarf_Die *die_mem)
4ea42b18 357{
378eeaad
MH
358 struct __find_variable_param fvp = { .name = name, .addr = addr};
359
360 return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
016f262e 361 die_mem);
4ea42b18
MH
362}
363
7df2f329
MH
364static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
365{
366 const char *name = data;
367
368 if ((dwarf_tag(die_mem) == DW_TAG_member) &&
82175633 369 die_compare_name(die_mem, name))
7df2f329
MH
370 return DIE_FIND_CB_FOUND;
371
372 return DIE_FIND_CB_SIBLING;
373}
374
375/* Find a member called 'name' */
376static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
377 Dwarf_Die *die_mem)
378{
379 return die_find_child(st_die, __die_find_member_cb, (void *)name,
380 die_mem);
381}
382
4ea42b18
MH
383/*
384 * Probe finder related functions
385 */
386
0e60836b 387static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
b7dcb857 388{
0e60836b
SD
389 struct probe_trace_arg_ref *ref;
390 ref = zalloc(sizeof(struct probe_trace_arg_ref));
b7dcb857
MH
391 if (ref != NULL)
392 ref->offset = offs;
393 return ref;
394}
395
4ea42b18 396/* Show a location */
b7dcb857 397static int convert_variable_location(Dwarf_Die *vr_die, struct probe_finder *pf)
4ea42b18 398{
b7dcb857
MH
399 Dwarf_Attribute attr;
400 Dwarf_Op *op;
401 size_t nops;
804b3606
MH
402 unsigned int regn;
403 Dwarf_Word offs = 0;
4235b045 404 bool ref = false;
4ea42b18 405 const char *regs;
0e60836b 406 struct probe_trace_arg *tvar = pf->tvar;
b7dcb857
MH
407 int ret;
408
632941c4
MH
409 if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
410 goto static_var;
411
b7dcb857
MH
412 /* TODO: handle more than 1 exprs */
413 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL ||
414 dwarf_getlocation_addr(&attr, pf->addr, &op, &nops, 1) <= 0 ||
415 nops == 0) {
416 /* TODO: Support const_value */
417 pr_err("Failed to find the location of %s at this address.\n"
418 " Perhaps, it has been optimized out.\n", pf->pvar->var);
419 return -ENOENT;
420 }
421
422 if (op->atom == DW_OP_addr) {
632941c4 423static_var:
b7dcb857
MH
424 /* Static variables on memory (not stack), make @varname */
425 ret = strlen(dwarf_diename(vr_die));
426 tvar->value = zalloc(ret + 2);
427 if (tvar->value == NULL)
428 return -ENOMEM;
429 snprintf(tvar->value, ret + 2, "@%s", dwarf_diename(vr_die));
430 tvar->ref = alloc_trace_arg_ref((long)offs);
431 if (tvar->ref == NULL)
432 return -ENOMEM;
433 return 0;
434 }
4ea42b18 435
4ea42b18 436 /* If this is based on frame buffer, set the offset */
804b3606 437 if (op->atom == DW_OP_fbreg) {
b55a87ad
MH
438 if (pf->fb_ops == NULL) {
439 pr_warning("The attribute of frame base is not "
440 "supported.\n");
441 return -ENOTSUP;
442 }
4235b045 443 ref = true;
804b3606
MH
444 offs = op->number;
445 op = &pf->fb_ops[0];
446 }
4ea42b18 447
804b3606
MH
448 if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
449 regn = op->atom - DW_OP_breg0;
450 offs += op->number;
4235b045 451 ref = true;
804b3606
MH
452 } else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) {
453 regn = op->atom - DW_OP_reg0;
454 } else if (op->atom == DW_OP_bregx) {
455 regn = op->number;
456 offs += op->number2;
4235b045 457 ref = true;
804b3606
MH
458 } else if (op->atom == DW_OP_regx) {
459 regn = op->number;
b55a87ad
MH
460 } else {
461 pr_warning("DW_OP %x is not supported.\n", op->atom);
462 return -ENOTSUP;
463 }
4ea42b18
MH
464
465 regs = get_arch_regstr(regn);
b55a87ad 466 if (!regs) {
cd932c59 467 pr_warning("Mapping for DWARF register number %u missing on this architecture.", regn);
b55a87ad
MH
468 return -ERANGE;
469 }
4ea42b18 470
02b95dad
MH
471 tvar->value = strdup(regs);
472 if (tvar->value == NULL)
473 return -ENOMEM;
474
4235b045 475 if (ref) {
b7dcb857 476 tvar->ref = alloc_trace_arg_ref((long)offs);
e334016f
MH
477 if (tvar->ref == NULL)
478 return -ENOMEM;
4235b045 479 }
b55a87ad 480 return 0;
4ea42b18
MH
481}
482
b55a87ad 483static int convert_variable_type(Dwarf_Die *vr_die,
0e60836b 484 struct probe_trace_arg *tvar,
73317b95 485 const char *cast)
4984912e 486{
0e60836b 487 struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
4984912e
MH
488 Dwarf_Die type;
489 char buf[16];
490 int ret;
491
73317b95
MH
492 /* TODO: check all types */
493 if (cast && strcmp(cast, "string") != 0) {
494 /* Non string type is OK */
495 tvar->type = strdup(cast);
496 return (tvar->type == NULL) ? -ENOMEM : 0;
497 }
498
b55a87ad
MH
499 if (die_get_real_type(vr_die, &type) == NULL) {
500 pr_warning("Failed to get a type information of %s.\n",
501 dwarf_diename(vr_die));
502 return -ENOENT;
503 }
4984912e 504
b2a3c12b
MH
505 pr_debug("%s type is %s.\n",
506 dwarf_diename(vr_die), dwarf_diename(&type));
507
73317b95
MH
508 if (cast && strcmp(cast, "string") == 0) { /* String type */
509 ret = dwarf_tag(&type);
510 if (ret != DW_TAG_pointer_type &&
511 ret != DW_TAG_array_type) {
512 pr_warning("Failed to cast into string: "
513 "%s(%s) is not a pointer nor array.",
514 dwarf_diename(vr_die), dwarf_diename(&type));
515 return -EINVAL;
516 }
517 if (ret == DW_TAG_pointer_type) {
518 if (die_get_real_type(&type, &type) == NULL) {
519 pr_warning("Failed to get a type information.");
520 return -ENOENT;
521 }
522 while (*ref_ptr)
523 ref_ptr = &(*ref_ptr)->next;
524 /* Add new reference with offset +0 */
0e60836b 525 *ref_ptr = zalloc(sizeof(struct probe_trace_arg_ref));
73317b95
MH
526 if (*ref_ptr == NULL) {
527 pr_warning("Out of memory error\n");
528 return -ENOMEM;
529 }
530 }
82175633
MH
531 if (!die_compare_name(&type, "char") &&
532 !die_compare_name(&type, "unsigned char")) {
73317b95
MH
533 pr_warning("Failed to cast into string: "
534 "%s is not (unsigned) char *.",
535 dwarf_diename(vr_die));
536 return -EINVAL;
537 }
538 tvar->type = strdup(cast);
539 return (tvar->type == NULL) ? -ENOMEM : 0;
540 }
541
4984912e
MH
542 ret = die_get_byte_size(&type) * 8;
543 if (ret) {
544 /* Check the bitwidth */
545 if (ret > MAX_BASIC_TYPE_BITS) {
b55a87ad
MH
546 pr_info("%s exceeds max-bitwidth."
547 " Cut down to %d bits.\n",
548 dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
4984912e
MH
549 ret = MAX_BASIC_TYPE_BITS;
550 }
551
552 ret = snprintf(buf, 16, "%c%d",
553 die_is_signed_type(&type) ? 's' : 'u', ret);
b55a87ad
MH
554 if (ret < 0 || ret >= 16) {
555 if (ret >= 16)
556 ret = -E2BIG;
557 pr_warning("Failed to convert variable type: %s\n",
558 strerror(-ret));
559 return ret;
560 }
73317b95
MH
561 tvar->type = strdup(buf);
562 if (tvar->type == NULL)
02b95dad 563 return -ENOMEM;
4984912e 564 }
b55a87ad 565 return 0;
4984912e
MH
566}
567
b55a87ad 568static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
7df2f329 569 struct perf_probe_arg_field *field,
0e60836b 570 struct probe_trace_arg_ref **ref_ptr,
4984912e 571 Dwarf_Die *die_mem)
7df2f329 572{
0e60836b 573 struct probe_trace_arg_ref *ref = *ref_ptr;
7df2f329
MH
574 Dwarf_Die type;
575 Dwarf_Word offs;
b2a3c12b 576 int ret, tag;
7df2f329
MH
577
578 pr_debug("converting %s in %s\n", field->name, varname);
b55a87ad
MH
579 if (die_get_real_type(vr_die, &type) == NULL) {
580 pr_warning("Failed to get the type of %s.\n", varname);
581 return -ENOENT;
582 }
b2a3c12b
MH
583 pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type));
584 tag = dwarf_tag(&type);
585
586 if (field->name[0] == '[' &&
587 (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) {
588 if (field->next)
589 /* Save original type for next field */
590 memcpy(die_mem, &type, sizeof(*die_mem));
591 /* Get the type of this array */
592 if (die_get_real_type(&type, &type) == NULL) {
593 pr_warning("Failed to get the type of %s.\n", varname);
594 return -ENOENT;
595 }
596 pr_debug2("Array real type: (%x)\n",
597 (unsigned)dwarf_dieoffset(&type));
598 if (tag == DW_TAG_pointer_type) {
0e60836b 599 ref = zalloc(sizeof(struct probe_trace_arg_ref));
b2a3c12b
MH
600 if (ref == NULL)
601 return -ENOMEM;
602 if (*ref_ptr)
603 (*ref_ptr)->next = ref;
604 else
605 *ref_ptr = ref;
606 }
607 ref->offset += die_get_byte_size(&type) * field->index;
608 if (!field->next)
609 /* Save vr_die for converting types */
610 memcpy(die_mem, vr_die, sizeof(*die_mem));
611 goto next;
612 } else if (tag == DW_TAG_pointer_type) {
613 /* Check the pointer and dereference */
b55a87ad
MH
614 if (!field->ref) {
615 pr_err("Semantic error: %s must be referred by '->'\n",
616 field->name);
617 return -EINVAL;
618 }
7df2f329 619 /* Get the type pointed by this pointer */
b55a87ad
MH
620 if (die_get_real_type(&type, &type) == NULL) {
621 pr_warning("Failed to get the type of %s.\n", varname);
622 return -ENOENT;
623 }
12e5a7ae 624 /* Verify it is a data structure */
b55a87ad
MH
625 if (dwarf_tag(&type) != DW_TAG_structure_type) {
626 pr_warning("%s is not a data structure.\n", varname);
627 return -EINVAL;
628 }
12e5a7ae 629
0e60836b 630 ref = zalloc(sizeof(struct probe_trace_arg_ref));
e334016f
MH
631 if (ref == NULL)
632 return -ENOMEM;
7df2f329
MH
633 if (*ref_ptr)
634 (*ref_ptr)->next = ref;
635 else
636 *ref_ptr = ref;
637 } else {
12e5a7ae 638 /* Verify it is a data structure */
b2a3c12b 639 if (tag != DW_TAG_structure_type) {
b55a87ad
MH
640 pr_warning("%s is not a data structure.\n", varname);
641 return -EINVAL;
642 }
b2a3c12b
MH
643 if (field->name[0] == '[') {
644 pr_err("Semantic error: %s is not a pointor nor array.",
645 varname);
646 return -EINVAL;
647 }
b55a87ad
MH
648 if (field->ref) {
649 pr_err("Semantic error: %s must be referred by '.'\n",
650 field->name);
651 return -EINVAL;
652 }
653 if (!ref) {
654 pr_warning("Structure on a register is not "
655 "supported yet.\n");
656 return -ENOTSUP;
657 }
7df2f329
MH
658 }
659
b55a87ad
MH
660 if (die_find_member(&type, field->name, die_mem) == NULL) {
661 pr_warning("%s(tyep:%s) has no member %s.\n", varname,
662 dwarf_diename(&type), field->name);
663 return -EINVAL;
664 }
7df2f329
MH
665
666 /* Get the offset of the field */
de1439d8
MH
667 ret = die_get_data_member_location(die_mem, &offs);
668 if (ret < 0) {
b55a87ad 669 pr_warning("Failed to get the offset of %s.\n", field->name);
de1439d8 670 return ret;
b55a87ad 671 }
7df2f329
MH
672 ref->offset += (long)offs;
673
b2a3c12b 674next:
7df2f329
MH
675 /* Converting next field */
676 if (field->next)
b55a87ad 677 return convert_variable_fields(die_mem, field->name,
de1439d8 678 field->next, &ref, die_mem);
b55a87ad
MH
679 else
680 return 0;
7df2f329
MH
681}
682
4ea42b18 683/* Show a variables in kprobe event format */
b55a87ad 684static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
4ea42b18 685{
4984912e 686 Dwarf_Die die_mem;
4ea42b18
MH
687 int ret;
688
b7dcb857
MH
689 pr_debug("Converting variable %s into trace event.\n",
690 dwarf_diename(vr_die));
804b3606 691
b7dcb857 692 ret = convert_variable_location(vr_die, pf);
b55a87ad
MH
693 if (ret == 0 && pf->pvar->field) {
694 ret = convert_variable_fields(vr_die, pf->pvar->var,
695 pf->pvar->field, &pf->tvar->ref,
696 &die_mem);
4984912e
MH
697 vr_die = &die_mem;
698 }
73317b95
MH
699 if (ret == 0)
700 ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
804b3606 701 /* *expr will be cached in libdw. Don't free it. */
b55a87ad 702 return ret;
4ea42b18
MH
703}
704
4ea42b18 705/* Find a variable in a subprogram die */
b55a87ad 706static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
4ea42b18 707{
b7dcb857 708 Dwarf_Die vr_die, *scopes;
11a1ca35 709 char buf[32], *ptr;
b7dcb857 710 int ret, nscopes;
4ea42b18 711
367e94c1
MH
712 if (!is_c_varname(pf->pvar->var)) {
713 /* Copy raw parameters */
714 pf->tvar->value = strdup(pf->pvar->var);
715 if (pf->tvar->value == NULL)
716 return -ENOMEM;
717 if (pf->pvar->type) {
718 pf->tvar->type = strdup(pf->pvar->type);
719 if (pf->tvar->type == NULL)
720 return -ENOMEM;
721 }
722 if (pf->pvar->name) {
723 pf->tvar->name = strdup(pf->pvar->name);
724 if (pf->tvar->name == NULL)
725 return -ENOMEM;
726 } else
727 pf->tvar->name = NULL;
728 return 0;
729 }
730
48481938 731 if (pf->pvar->name)
02b95dad 732 pf->tvar->name = strdup(pf->pvar->name);
48481938 733 else {
02b95dad
MH
734 ret = synthesize_perf_probe_arg(pf->pvar, buf, 32);
735 if (ret < 0)
736 return ret;
11a1ca35
MH
737 ptr = strchr(buf, ':'); /* Change type separator to _ */
738 if (ptr)
739 *ptr = '_';
02b95dad 740 pf->tvar->name = strdup(buf);
48481938 741 }
02b95dad
MH
742 if (pf->tvar->name == NULL)
743 return -ENOMEM;
48481938 744
b55a87ad
MH
745 pr_debug("Searching '%s' variable in context.\n",
746 pf->pvar->var);
747 /* Search child die for local variables and parameters. */
378eeaad 748 if (die_find_variable_at(sp_die, pf->pvar->var, pf->addr, &vr_die))
b7dcb857
MH
749 ret = convert_variable(&vr_die, pf);
750 else {
751 /* Search upper class */
752 nscopes = dwarf_getscopes_die(sp_die, &scopes);
632941c4
MH
753 while (nscopes-- > 1) {
754 pr_debug("Searching variables in %s\n",
755 dwarf_diename(&scopes[nscopes]));
756 /* We should check this scope, so give dummy address */
757 if (die_find_variable_at(&scopes[nscopes],
758 pf->pvar->var, 0,
759 &vr_die)) {
b7dcb857 760 ret = convert_variable(&vr_die, pf);
632941c4
MH
761 goto found;
762 }
763 }
764 if (scopes)
b7dcb857 765 free(scopes);
632941c4 766 ret = -ENOENT;
b7dcb857 767 }
632941c4 768found:
b7dcb857 769 if (ret < 0)
b55a87ad
MH
770 pr_warning("Failed to find '%s' in this function.\n",
771 pf->pvar->var);
b7dcb857 772 return ret;
4ea42b18
MH
773}
774
4ea42b18 775/* Show a probe point to output buffer */
b55a87ad 776static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
4ea42b18 777{
0e60836b 778 struct probe_trace_event *tev;
e92b85e1
MH
779 Dwarf_Addr eaddr;
780 Dwarf_Die die_mem;
804b3606 781 const char *name;
4235b045 782 int ret, i;
804b3606
MH
783 Dwarf_Attribute fb_attr;
784 size_t nops;
4ea42b18 785
ef4a3565
MH
786 if (pf->ntevs == pf->max_tevs) {
787 pr_warning("Too many( > %d) probe point found.\n",
788 pf->max_tevs);
b55a87ad
MH
789 return -ERANGE;
790 }
4235b045
MH
791 tev = &pf->tevs[pf->ntevs++];
792
e92b85e1
MH
793 /* If no real subprogram, find a real one */
794 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
95a3e4c4 795 sp_die = die_find_real_subprogram(&pf->cu_die,
e92b85e1 796 pf->addr, &die_mem);
b55a87ad
MH
797 if (!sp_die) {
798 pr_warning("Failed to find probe point in any "
799 "functions.\n");
800 return -ENOENT;
801 }
e92b85e1
MH
802 }
803
4235b045 804 /* Copy the name of probe point */
804b3606
MH
805 name = dwarf_diename(sp_die);
806 if (name) {
b55a87ad
MH
807 if (dwarf_entrypc(sp_die, &eaddr) != 0) {
808 pr_warning("Failed to get entry pc of %s\n",
809 dwarf_diename(sp_die));
810 return -ENOENT;
811 }
02b95dad
MH
812 tev->point.symbol = strdup(name);
813 if (tev->point.symbol == NULL)
814 return -ENOMEM;
4235b045
MH
815 tev->point.offset = (unsigned long)(pf->addr - eaddr);
816 } else
4ea42b18 817 /* This function has no name. */
4235b045
MH
818 tev->point.offset = (unsigned long)pf->addr;
819
04ddd04b
MH
820 /* Return probe must be on the head of a subprogram */
821 if (pf->pev->point.retprobe) {
822 if (tev->point.offset != 0) {
823 pr_warning("Return probe must be on the head of"
824 " a real function\n");
825 return -EINVAL;
826 }
827 tev->point.retprobe = true;
828 }
829
4235b045
MH
830 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
831 tev->point.offset);
4ea42b18 832
804b3606
MH
833 /* Get the frame base attribute/ops */
834 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
d0cb4260 835 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
a34a9854 836 if (ret <= 0 || nops == 0) {
804b3606 837 pf->fb_ops = NULL;
7752f1b0 838#if _ELFUTILS_PREREQ(0, 142)
a34a9854
MH
839 } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
840 pf->cfi != NULL) {
841 Dwarf_Frame *frame;
b55a87ad
MH
842 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
843 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
844 pr_warning("Failed to get CFA on 0x%jx\n",
845 (uintmax_t)pf->addr);
846 return -ENOENT;
847 }
7752f1b0 848#endif
a34a9854 849 }
804b3606 850
4ea42b18 851 /* Find each argument */
4235b045 852 tev->nargs = pf->pev->nargs;
0e60836b 853 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
e334016f
MH
854 if (tev->args == NULL)
855 return -ENOMEM;
4235b045
MH
856 for (i = 0; i < pf->pev->nargs; i++) {
857 pf->pvar = &pf->pev->args[i];
858 pf->tvar = &tev->args[i];
b55a87ad
MH
859 ret = find_variable(sp_die, pf);
860 if (ret != 0)
861 return ret;
4ea42b18 862 }
804b3606
MH
863
864 /* *pf->fb_ops will be cached in libdw. Don't free it. */
865 pf->fb_ops = NULL;
b55a87ad 866 return 0;
4ea42b18
MH
867}
868
4ea42b18 869/* Find probe point from its line number */
b55a87ad 870static int find_probe_point_by_line(struct probe_finder *pf)
4ea42b18 871{
804b3606
MH
872 Dwarf_Lines *lines;
873 Dwarf_Line *line;
874 size_t nlines, i;
e92b85e1 875 Dwarf_Addr addr;
804b3606 876 int lineno;
b55a87ad 877 int ret = 0;
4ea42b18 878
b55a87ad
MH
879 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
880 pr_warning("No source lines found in this CU.\n");
881 return -ENOENT;
882 }
4ea42b18 883
b55a87ad 884 for (i = 0; i < nlines && ret == 0; i++) {
804b3606 885 line = dwarf_onesrcline(lines, i);
b55a87ad
MH
886 if (dwarf_lineno(line, &lineno) != 0 ||
887 lineno != pf->lno)
4ea42b18
MH
888 continue;
889
804b3606
MH
890 /* TODO: Get fileno from line, but how? */
891 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
892 continue;
b0ef0732 893
b55a87ad
MH
894 if (dwarf_lineaddr(line, &addr) != 0) {
895 pr_warning("Failed to get the address of the line.\n");
896 return -ENOENT;
897 }
804b3606
MH
898 pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
899 (int)i, lineno, (uintmax_t)addr);
4ea42b18 900 pf->addr = addr;
804b3606 901
b55a87ad 902 ret = convert_probe_point(NULL, pf);
4ea42b18
MH
903 /* Continuing, because target line might be inlined. */
904 }
b55a87ad 905 return ret;
4ea42b18
MH
906}
907
2a9c8c36
MH
908/* Find lines which match lazy pattern */
909static int find_lazy_match_lines(struct list_head *head,
910 const char *fname, const char *pat)
911{
912 char *fbuf, *p1, *p2;
b448c4b6 913 int fd, line, nlines = -1;
2a9c8c36
MH
914 struct stat st;
915
916 fd = open(fname, O_RDONLY);
b55a87ad
MH
917 if (fd < 0) {
918 pr_warning("Failed to open %s: %s\n", fname, strerror(-fd));
b448c4b6 919 return -errno;
b55a87ad
MH
920 }
921
b448c4b6 922 if (fstat(fd, &st) < 0) {
b55a87ad
MH
923 pr_warning("Failed to get the size of %s: %s\n",
924 fname, strerror(errno));
b448c4b6
ACM
925 nlines = -errno;
926 goto out_close;
b55a87ad 927 }
b448c4b6
ACM
928
929 nlines = -ENOMEM;
930 fbuf = malloc(st.st_size + 2);
931 if (fbuf == NULL)
932 goto out_close;
933 if (read(fd, fbuf, st.st_size) < 0) {
b55a87ad 934 pr_warning("Failed to read %s: %s\n", fname, strerror(errno));
b448c4b6
ACM
935 nlines = -errno;
936 goto out_free_fbuf;
b55a87ad 937 }
2a9c8c36
MH
938 fbuf[st.st_size] = '\n'; /* Dummy line */
939 fbuf[st.st_size + 1] = '\0';
940 p1 = fbuf;
941 line = 1;
b448c4b6 942 nlines = 0;
2a9c8c36
MH
943 while ((p2 = strchr(p1, '\n')) != NULL) {
944 *p2 = '\0';
945 if (strlazymatch(p1, pat)) {
946 line_list__add_line(head, line);
947 nlines++;
948 }
949 line++;
950 p1 = p2 + 1;
951 }
b448c4b6 952out_free_fbuf:
2a9c8c36 953 free(fbuf);
b448c4b6
ACM
954out_close:
955 close(fd);
2a9c8c36
MH
956 return nlines;
957}
958
959/* Find probe points from lazy pattern */
b55a87ad 960static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
2a9c8c36
MH
961{
962 Dwarf_Lines *lines;
963 Dwarf_Line *line;
964 size_t nlines, i;
965 Dwarf_Addr addr;
966 Dwarf_Die die_mem;
967 int lineno;
b55a87ad 968 int ret = 0;
2a9c8c36
MH
969
970 if (list_empty(&pf->lcache)) {
971 /* Matching lazy line pattern */
972 ret = find_lazy_match_lines(&pf->lcache, pf->fname,
4235b045 973 pf->pev->point.lazy_line);
b55a87ad
MH
974 if (ret == 0) {
975 pr_debug("No matched lines found in %s.\n", pf->fname);
976 return 0;
977 } else if (ret < 0)
978 return ret;
2a9c8c36
MH
979 }
980
b55a87ad
MH
981 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
982 pr_warning("No source lines found in this CU.\n");
983 return -ENOENT;
984 }
985
986 for (i = 0; i < nlines && ret >= 0; i++) {
2a9c8c36
MH
987 line = dwarf_onesrcline(lines, i);
988
b55a87ad
MH
989 if (dwarf_lineno(line, &lineno) != 0 ||
990 !line_list__has_line(&pf->lcache, lineno))
2a9c8c36
MH
991 continue;
992
993 /* TODO: Get fileno from line, but how? */
994 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
995 continue;
996
b55a87ad
MH
997 if (dwarf_lineaddr(line, &addr) != 0) {
998 pr_debug("Failed to get the address of line %d.\n",
999 lineno);
1000 continue;
1001 }
2a9c8c36
MH
1002 if (sp_die) {
1003 /* Address filtering 1: does sp_die include addr? */
1004 if (!dwarf_haspc(sp_die, addr))
1005 continue;
1006 /* Address filtering 2: No child include addr? */
95a3e4c4 1007 if (die_find_inlinefunc(sp_die, addr, &die_mem))
2a9c8c36
MH
1008 continue;
1009 }
1010
1011 pr_debug("Probe line found: line[%d]:%d addr:0x%llx\n",
1012 (int)i, lineno, (unsigned long long)addr);
1013 pf->addr = addr;
1014
b55a87ad 1015 ret = convert_probe_point(sp_die, pf);
2a9c8c36
MH
1016 /* Continuing, because target line might be inlined. */
1017 }
1018 /* TODO: deallocate lines, but how? */
b55a87ad 1019 return ret;
2a9c8c36
MH
1020}
1021
b55a87ad
MH
1022/* Callback parameter with return value */
1023struct dwarf_callback_param {
1024 void *data;
1025 int retval;
1026};
1027
e92b85e1
MH
1028static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
1029{
b55a87ad
MH
1030 struct dwarf_callback_param *param = data;
1031 struct probe_finder *pf = param->data;
4235b045 1032 struct perf_probe_point *pp = &pf->pev->point;
b55a87ad 1033 Dwarf_Addr addr;
e92b85e1 1034
2a9c8c36 1035 if (pp->lazy_line)
b55a87ad 1036 param->retval = find_probe_point_lazy(in_die, pf);
2a9c8c36
MH
1037 else {
1038 /* Get probe address */
b55a87ad
MH
1039 if (dwarf_entrypc(in_die, &addr) != 0) {
1040 pr_warning("Failed to get entry pc of %s.\n",
1041 dwarf_diename(in_die));
1042 param->retval = -ENOENT;
1043 return DWARF_CB_ABORT;
1044 }
1045 pf->addr = addr;
2a9c8c36
MH
1046 pf->addr += pp->offset;
1047 pr_debug("found inline addr: 0x%jx\n",
1048 (uintmax_t)pf->addr);
1049
b55a87ad 1050 param->retval = convert_probe_point(in_die, pf);
5d1ee041
MH
1051 if (param->retval < 0)
1052 return DWARF_CB_ABORT;
2a9c8c36 1053 }
e92b85e1 1054
e92b85e1
MH
1055 return DWARF_CB_OK;
1056}
804b3606 1057
4ea42b18 1058/* Search function from function name */
e92b85e1 1059static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
4ea42b18 1060{
b55a87ad
MH
1061 struct dwarf_callback_param *param = data;
1062 struct probe_finder *pf = param->data;
4235b045 1063 struct perf_probe_point *pp = &pf->pev->point;
4ea42b18 1064
e92b85e1
MH
1065 /* Check tag and diename */
1066 if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
82175633 1067 !die_compare_name(sp_die, pp->function))
b55a87ad 1068 return DWARF_CB_OK;
e92b85e1 1069
2a9c8c36 1070 pf->fname = dwarf_decl_file(sp_die);
e92b85e1 1071 if (pp->line) { /* Function relative line */
e92b85e1
MH
1072 dwarf_decl_line(sp_die, &pf->lno);
1073 pf->lno += pp->line;
b55a87ad 1074 param->retval = find_probe_point_by_line(pf);
e92b85e1
MH
1075 } else if (!dwarf_func_inline(sp_die)) {
1076 /* Real function */
2a9c8c36 1077 if (pp->lazy_line)
b55a87ad 1078 param->retval = find_probe_point_lazy(sp_die, pf);
2a9c8c36 1079 else {
b55a87ad
MH
1080 if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
1081 pr_warning("Failed to get entry pc of %s.\n",
1082 dwarf_diename(sp_die));
1083 param->retval = -ENOENT;
1084 return DWARF_CB_ABORT;
1085 }
2a9c8c36
MH
1086 pf->addr += pp->offset;
1087 /* TODO: Check the address in this function */
b55a87ad 1088 param->retval = convert_probe_point(sp_die, pf);
2a9c8c36 1089 }
b55a87ad
MH
1090 } else {
1091 struct dwarf_callback_param _param = {.data = (void *)pf,
1092 .retval = 0};
e92b85e1 1093 /* Inlined function: search instances */
b55a87ad
MH
1094 dwarf_func_inline_instances(sp_die, probe_point_inline_cb,
1095 &_param);
1096 param->retval = _param.retval;
1097 }
e92b85e1 1098
b55a87ad 1099 return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
4ea42b18
MH
1100}
1101
b55a87ad 1102static int find_probe_point_by_func(struct probe_finder *pf)
4ea42b18 1103{
b55a87ad
MH
1104 struct dwarf_callback_param _param = {.data = (void *)pf,
1105 .retval = 0};
1106 dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
1107 return _param.retval;
4ea42b18
MH
1108}
1109
0e60836b
SD
1110/* Find probe_trace_events specified by perf_probe_event from debuginfo */
1111int find_probe_trace_events(int fd, struct perf_probe_event *pev,
1112 struct probe_trace_event **tevs, int max_tevs)
4ea42b18 1113{
ef4a3565 1114 struct probe_finder pf = {.pev = pev, .max_tevs = max_tevs};
4235b045 1115 struct perf_probe_point *pp = &pev->point;
804b3606
MH
1116 Dwarf_Off off, noff;
1117 size_t cuhl;
1118 Dwarf_Die *diep;
1119 Dwarf *dbg;
b55a87ad 1120 int ret = 0;
804b3606 1121
0e60836b 1122 pf.tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs);
e334016f
MH
1123 if (pf.tevs == NULL)
1124 return -ENOMEM;
4235b045
MH
1125 *tevs = pf.tevs;
1126 pf.ntevs = 0;
1127
804b3606 1128 dbg = dwarf_begin(fd, DWARF_C_READ);
b55a87ad
MH
1129 if (!dbg) {
1130 pr_warning("No dwarf info found in the vmlinux - "
1131 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
b448c4b6
ACM
1132 free(pf.tevs);
1133 *tevs = NULL;
b55a87ad
MH
1134 return -EBADF;
1135 }
4ea42b18 1136
7752f1b0 1137#if _ELFUTILS_PREREQ(0, 142)
a34a9854
MH
1138 /* Get the call frame information from this dwarf */
1139 pf.cfi = dwarf_getcfi(dbg);
7752f1b0 1140#endif
a34a9854 1141
804b3606 1142 off = 0;
2a9c8c36 1143 line_list__init(&pf.lcache);
804b3606 1144 /* Loop on CUs (Compilation Unit) */
b55a87ad
MH
1145 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) &&
1146 ret >= 0) {
4ea42b18 1147 /* Get the DIE(Debugging Information Entry) of this CU */
804b3606
MH
1148 diep = dwarf_offdie(dbg, off + cuhl, &pf.cu_die);
1149 if (!diep)
1150 continue;
4ea42b18
MH
1151
1152 /* Check if target file is included. */
1153 if (pp->file)
2a9c8c36 1154 pf.fname = cu_find_realpath(&pf.cu_die, pp->file);
804b3606 1155 else
2a9c8c36 1156 pf.fname = NULL;
4ea42b18 1157
2a9c8c36 1158 if (!pp->file || pf.fname) {
4ea42b18 1159 if (pp->function)
b55a87ad 1160 ret = find_probe_point_by_func(&pf);
2a9c8c36 1161 else if (pp->lazy_line)
b55a87ad 1162 ret = find_probe_point_lazy(NULL, &pf);
b0ef0732
MH
1163 else {
1164 pf.lno = pp->line;
b55a87ad 1165 ret = find_probe_point_by_line(&pf);
b0ef0732 1166 }
4ea42b18 1167 }
804b3606 1168 off = noff;
4ea42b18 1169 }
2a9c8c36 1170 line_list__free(&pf.lcache);
804b3606 1171 dwarf_end(dbg);
4ea42b18 1172
b55a87ad 1173 return (ret < 0) ? ret : pf.ntevs;
4ea42b18
MH
1174}
1175
fb1587d8
MH
1176/* Reverse search */
1177int find_perf_probe_point(int fd, unsigned long addr,
1178 struct perf_probe_point *ppt)
1179{
1180 Dwarf_Die cudie, spdie, indie;
1181 Dwarf *dbg;
1182 Dwarf_Line *line;
1183 Dwarf_Addr laddr, eaddr;
1184 const char *tmp;
1185 int lineno, ret = 0;
b55a87ad 1186 bool found = false;
fb1587d8
MH
1187
1188 dbg = dwarf_begin(fd, DWARF_C_READ);
1189 if (!dbg)
b55a87ad 1190 return -EBADF;
fb1587d8
MH
1191
1192 /* Find cu die */
75ec5a24
MH
1193 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) {
1194 ret = -EINVAL;
1195 goto end;
1196 }
fb1587d8
MH
1197
1198 /* Find a corresponding line */
1199 line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr);
1200 if (line) {
b55a87ad
MH
1201 if (dwarf_lineaddr(line, &laddr) == 0 &&
1202 (Dwarf_Addr)addr == laddr &&
1203 dwarf_lineno(line, &lineno) == 0) {
fb1587d8 1204 tmp = dwarf_linesrc(line, NULL, NULL);
b55a87ad
MH
1205 if (tmp) {
1206 ppt->line = lineno;
02b95dad
MH
1207 ppt->file = strdup(tmp);
1208 if (ppt->file == NULL) {
1209 ret = -ENOMEM;
1210 goto end;
1211 }
b55a87ad
MH
1212 found = true;
1213 }
fb1587d8
MH
1214 }
1215 }
1216
1217 /* Find a corresponding function */
1218 if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) {
1219 tmp = dwarf_diename(&spdie);
b55a87ad 1220 if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0)
fb1587d8
MH
1221 goto end;
1222
b55a87ad
MH
1223 if (ppt->line) {
1224 if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
1225 &indie)) {
1226 /* addr in an inline function */
1227 tmp = dwarf_diename(&indie);
1228 if (!tmp)
1229 goto end;
1230 ret = dwarf_decl_line(&indie, &lineno);
1231 } else {
1232 if (eaddr == addr) { /* Function entry */
1233 lineno = ppt->line;
1234 ret = 0;
1235 } else
1236 ret = dwarf_decl_line(&spdie, &lineno);
1237 }
1238 if (ret == 0) {
1239 /* Make a relative line number */
1240 ppt->line -= lineno;
1241 goto found;
1242 }
fb1587d8 1243 }
b55a87ad
MH
1244 /* We don't have a line number, let's use offset */
1245 ppt->offset = addr - (unsigned long)eaddr;
1246found:
02b95dad
MH
1247 ppt->function = strdup(tmp);
1248 if (ppt->function == NULL) {
1249 ret = -ENOMEM;
1250 goto end;
1251 }
b55a87ad 1252 found = true;
fb1587d8
MH
1253 }
1254
1255end:
1256 dwarf_end(dbg);
b55a87ad
MH
1257 if (ret >= 0)
1258 ret = found ? 1 : 0;
fb1587d8
MH
1259 return ret;
1260}
1261
f6c903f5
MH
1262/* Add a line and store the src path */
1263static int line_range_add_line(const char *src, unsigned int lineno,
1264 struct line_range *lr)
1265{
7cf0b79e 1266 /* Copy source path */
f6c903f5 1267 if (!lr->path) {
7cf0b79e
MH
1268 lr->path = strdup(src);
1269 if (lr->path == NULL)
1270 return -ENOMEM;
f6c903f5
MH
1271 }
1272 return line_list__add_line(&lr->line_list, lineno);
1273}
1274
1275/* Search function declaration lines */
1276static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data)
1277{
1278 struct dwarf_callback_param *param = data;
1279 struct line_finder *lf = param->data;
1280 const char *src;
1281 int lineno;
1282
1283 src = dwarf_decl_file(sp_die);
1284 if (src && strtailcmp(src, lf->fname) != 0)
1285 return DWARF_CB_OK;
1286
1287 if (dwarf_decl_line(sp_die, &lineno) != 0 ||
1288 (lf->lno_s > lineno || lf->lno_e < lineno))
1289 return DWARF_CB_OK;
1290
1291 param->retval = line_range_add_line(src, lineno, lf->lr);
5d1ee041
MH
1292 if (param->retval < 0)
1293 return DWARF_CB_ABORT;
f6c903f5
MH
1294 return DWARF_CB_OK;
1295}
1296
1297static int find_line_range_func_decl_lines(struct line_finder *lf)
1298{
1299 struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
1300 dwarf_getfuncs(&lf->cu_die, line_range_funcdecl_cb, &param, 0);
1301 return param.retval;
1302}
fb1587d8 1303
631c9def 1304/* Find line range from its line number */
b55a87ad 1305static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
631c9def 1306{
804b3606
MH
1307 Dwarf_Lines *lines;
1308 Dwarf_Line *line;
1309 size_t nlines, i;
631c9def 1310 Dwarf_Addr addr;
f6c903f5 1311 int lineno, ret = 0;
804b3606 1312 const char *src;
161a26b0 1313 Dwarf_Die die_mem;
631c9def 1314
2a9c8c36 1315 line_list__init(&lf->lr->line_list);
b55a87ad
MH
1316 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
1317 pr_warning("No source lines found in this CU.\n");
1318 return -ENOENT;
1319 }
631c9def 1320
f6c903f5 1321 /* Search probable lines on lines list */
804b3606
MH
1322 for (i = 0; i < nlines; i++) {
1323 line = dwarf_onesrcline(lines, i);
b55a87ad
MH
1324 if (dwarf_lineno(line, &lineno) != 0 ||
1325 (lf->lno_s > lineno || lf->lno_e < lineno))
631c9def
MH
1326 continue;
1327
161a26b0
MH
1328 if (sp_die) {
1329 /* Address filtering 1: does sp_die include addr? */
b55a87ad
MH
1330 if (dwarf_lineaddr(line, &addr) != 0 ||
1331 !dwarf_haspc(sp_die, addr))
161a26b0
MH
1332 continue;
1333
1334 /* Address filtering 2: No child include addr? */
95a3e4c4 1335 if (die_find_inlinefunc(sp_die, addr, &die_mem))
161a26b0
MH
1336 continue;
1337 }
1338
804b3606
MH
1339 /* TODO: Get fileno from line, but how? */
1340 src = dwarf_linesrc(line, NULL, NULL);
1341 if (strtailcmp(src, lf->fname) != 0)
631c9def
MH
1342 continue;
1343
f6c903f5
MH
1344 ret = line_range_add_line(src, lineno, lf->lr);
1345 if (ret < 0)
1346 return ret;
631c9def 1347 }
f6c903f5
MH
1348
1349 /*
1350 * Dwarf lines doesn't include function declarations. We have to
1351 * check functions list or given function.
1352 */
1353 if (sp_die) {
1354 src = dwarf_decl_file(sp_die);
1355 if (src && dwarf_decl_line(sp_die, &lineno) == 0 &&
1356 (lf->lno_s <= lineno && lf->lno_e >= lineno))
1357 ret = line_range_add_line(src, lineno, lf->lr);
1358 } else
1359 ret = find_line_range_func_decl_lines(lf);
1360
804b3606 1361 /* Update status */
f6c903f5
MH
1362 if (ret >= 0)
1363 if (!list_empty(&lf->lr->line_list))
1364 ret = lf->found = 1;
1365 else
1366 ret = 0; /* Lines are not found */
804b3606
MH
1367 else {
1368 free(lf->lr->path);
1369 lf->lr->path = NULL;
1370 }
f6c903f5 1371 return ret;
631c9def
MH
1372}
1373
161a26b0
MH
1374static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
1375{
b55a87ad
MH
1376 struct dwarf_callback_param *param = data;
1377
1378 param->retval = find_line_range_by_line(in_die, param->data);
161a26b0
MH
1379 return DWARF_CB_ABORT; /* No need to find other instances */
1380}
1381
631c9def 1382/* Search function from function name */
e92b85e1 1383static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
631c9def 1384{
b55a87ad
MH
1385 struct dwarf_callback_param *param = data;
1386 struct line_finder *lf = param->data;
631c9def 1387 struct line_range *lr = lf->lr;
631c9def 1388
e92b85e1 1389 if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
82175633 1390 die_compare_name(sp_die, lr->function)) {
e92b85e1
MH
1391 lf->fname = dwarf_decl_file(sp_die);
1392 dwarf_decl_line(sp_die, &lr->offset);
804b3606 1393 pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
631c9def 1394 lf->lno_s = lr->offset + lr->start;
d3b63d7a
MH
1395 if (lf->lno_s < 0) /* Overflow */
1396 lf->lno_s = INT_MAX;
1397 lf->lno_e = lr->offset + lr->end;
1398 if (lf->lno_e < 0) /* Overflow */
804b3606 1399 lf->lno_e = INT_MAX;
d3b63d7a 1400 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
631c9def
MH
1401 lr->start = lf->lno_s;
1402 lr->end = lf->lno_e;
b55a87ad
MH
1403 if (dwarf_func_inline(sp_die)) {
1404 struct dwarf_callback_param _param;
1405 _param.data = (void *)lf;
1406 _param.retval = 0;
161a26b0 1407 dwarf_func_inline_instances(sp_die,
b55a87ad
MH
1408 line_range_inline_cb,
1409 &_param);
1410 param->retval = _param.retval;
1411 } else
1412 param->retval = find_line_range_by_line(sp_die, lf);
1413 return DWARF_CB_ABORT;
631c9def 1414 }
b55a87ad 1415 return DWARF_CB_OK;
631c9def
MH
1416}
1417
b55a87ad 1418static int find_line_range_by_func(struct line_finder *lf)
631c9def 1419{
b55a87ad
MH
1420 struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
1421 dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
1422 return param.retval;
631c9def
MH
1423}
1424
1425int find_line_range(int fd, struct line_range *lr)
1426{
804b3606 1427 struct line_finder lf = {.lr = lr, .found = 0};
b55a87ad 1428 int ret = 0;
804b3606
MH
1429 Dwarf_Off off = 0, noff;
1430 size_t cuhl;
1431 Dwarf_Die *diep;
1432 Dwarf *dbg;
6a330a3c 1433 const char *comp_dir;
804b3606
MH
1434
1435 dbg = dwarf_begin(fd, DWARF_C_READ);
b55a87ad
MH
1436 if (!dbg) {
1437 pr_warning("No dwarf info found in the vmlinux - "
1438 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1439 return -EBADF;
1440 }
631c9def 1441
804b3606 1442 /* Loop on CUs (Compilation Unit) */
b55a87ad
MH
1443 while (!lf.found && ret >= 0) {
1444 if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0)
631c9def
MH
1445 break;
1446
1447 /* Get the DIE(Debugging Information Entry) of this CU */
804b3606
MH
1448 diep = dwarf_offdie(dbg, off + cuhl, &lf.cu_die);
1449 if (!diep)
1450 continue;
631c9def
MH
1451
1452 /* Check if target file is included. */
1453 if (lr->file)
2a9c8c36 1454 lf.fname = cu_find_realpath(&lf.cu_die, lr->file);
804b3606 1455 else
2a9c8c36 1456 lf.fname = 0;
631c9def 1457
2a9c8c36 1458 if (!lr->file || lf.fname) {
631c9def 1459 if (lr->function)
b55a87ad 1460 ret = find_line_range_by_func(&lf);
631c9def
MH
1461 else {
1462 lf.lno_s = lr->start;
d3b63d7a 1463 lf.lno_e = lr->end;
b55a87ad 1464 ret = find_line_range_by_line(NULL, &lf);
631c9def 1465 }
631c9def 1466 }
804b3606 1467 off = noff;
631c9def 1468 }
6a330a3c
MH
1469
1470 /* Store comp_dir */
1471 if (lf.found) {
1472 comp_dir = cu_get_comp_dir(&lf.cu_die);
1473 if (comp_dir) {
1474 lr->comp_dir = strdup(comp_dir);
1475 if (!lr->comp_dir)
1476 ret = -ENOMEM;
1477 }
1478 }
1479
7cf0b79e 1480 pr_debug("path: %s\n", lr->path);
804b3606 1481 dwarf_end(dbg);
b55a87ad
MH
1482
1483 return (ret < 0) ? ret : lf.found;
631c9def
MH
1484}
1485