blob: a274fd0c143eaa997e57ccdd3f34b006848f89dc [file] [log] [blame]
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001/*
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>
Ian Munsiecd932c52010-04-20 16:58:32 +100034#include <dwarf-regs.h>
Masami Hiramatsu074fc0e2009-10-16 20:08:01 -040035
Masami Hiramatsu89c69c02009-10-16 20:08:10 -040036#include "event.h"
37#include "debug.h"
Masami Hiramatsu074fc0e2009-10-16 20:08:01 -040038#include "util.h"
Chase Douglas9ed7e1b2010-06-14 15:26:30 -040039#include "symbol.h"
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -040040#include "probe-finder.h"
41
Masami Hiramatsu49849122010-04-12 13:17:15 -040042/* Kprobe tracer basic type is up to u64 */
43#define MAX_BASIC_TYPE_BITS 64
44
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -040045/*
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);
Juha Leppanend56728b2009-12-07 12:00:40 -050053 while (--i1 >= 0 && --i2 >= 0) {
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -040054 if (s1[i1] != s2[i2])
55 return s1[i1] - s2[i2];
56 }
57 return 0;
58}
59
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -050060/* Line number list operations */
61
62/* Add a line to line number list */
Masami Hiramatsud3b63d72010-04-14 18:39:42 -040063static int line_list__add_line(struct list_head *head, int line)
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -050064{
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 */
Masami Hiramatsue334016f12010-04-12 13:17:49 -040074 return 1;
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -050075 }
76 /* List is empty, or the smallest entry */
77 p = head;
78found:
79 pr_debug("line list: add a line %u\n", line);
Masami Hiramatsue334016f12010-04-12 13:17:49 -040080 ln = zalloc(sizeof(struct line_node));
81 if (ln == NULL)
82 return -ENOMEM;
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -050083 ln->line = line;
84 INIT_LIST_HEAD(&ln->list);
85 list_add(&ln->list, p);
Masami Hiramatsue334016f12010-04-12 13:17:49 -040086 return 0;
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -050087}
88
89/* Check if the line in line number list */
Masami Hiramatsud3b63d72010-04-14 18:39:42 -040090static int line_list__has_line(struct list_head *head, int line)
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -050091{
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)
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400123{
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500124 Dwarf_Files *files;
125 size_t nfiles, i;
Arnaldo Carvalho de Meloaccd3cc2010-03-05 12:51:04 -0300126 const char *src = NULL;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400127 int ret;
128
129 if (!fname)
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500130 return NULL;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -0500131
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500132 ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500133 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;
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500140 }
Masami Hiramatsuc9e38582010-04-02 12:50:45 -0400141 if (i == nfiles)
142 return NULL;
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500143 return src;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -0500144}
145
Masami Hiramatsu6a330a32010-07-09 18:29:11 +0900146/* 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
Masami Hiramatsu016f2622010-03-16 18:05:58 -0400155/* 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);
Masami Hiramatsu82175632010-07-09 18:29:17 +0900160 return name ? (strcmp(tname, name) == 0) : false;
Masami Hiramatsu016f2622010-03-16 18:05:58 -0400161}
162
Masami Hiramatsu4046b8b2010-10-21 19:13:02 +0900163/* 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
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900175/* Get a type die, but skip qualifiers */
176static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400177{
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400178 int tag;
179
180 do {
Masami Hiramatsu4046b8b2010-10-21 19:13:02 +0900181 vr_die = die_get_type(vr_die, die_mem);
182 if (!vr_die)
183 break;
184 tag = dwarf_tag(vr_die);
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400185 } while (tag == DW_TAG_const_type ||
186 tag == DW_TAG_restrict_type ||
187 tag == DW_TAG_volatile_type ||
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900188 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);
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400199
Masami Hiramatsu4046b8b2010-10-21 19:13:02 +0900200 return vr_die;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400201}
202
Masami Hiramatsu49849122010-04-12 13:17:15 -0400203static 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
Masami Hiramatsude1439d2010-04-14 17:44:00 -0300228/* 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
Masami Hiramatsu016f2622010-03-16 18:05:58 -0400255/* 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
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500291struct __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)
297{
298 struct __addr_die_search_param *ad = data;
299
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}
307
308/* Search a real subprogram including this line, */
Masami Hiramatsu95a3e4c2010-03-16 18:05:51 -0400309static Dwarf_Die *die_find_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr,
310 Dwarf_Die *die_mem)
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500311{
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;
320}
321
Masami Hiramatsu016f2622010-03-16 18:05:58 -0400322/* die_find callback for inline function search */
323static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
324{
325 Dwarf_Addr *addr = data;
326
327 if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
328 dwarf_haspc(die_mem, *addr))
329 return DIE_FIND_CB_FOUND;
330
331 return DIE_FIND_CB_CONTINUE;
332}
333
Masami Hiramatsu161a26b2010-02-25 08:35:57 -0500334/* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */
Masami Hiramatsu95a3e4c2010-03-16 18:05:51 -0400335static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
336 Dwarf_Die *die_mem)
Masami Hiramatsu161a26b2010-02-25 08:35:57 -0500337{
Masami Hiramatsu016f2622010-03-16 18:05:58 -0400338 return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
Masami Hiramatsu161a26b2010-02-25 08:35:57 -0500339}
340
Masami Hiramatsu378eeaa2010-10-21 19:13:09 +0900341struct __find_variable_param {
342 const char *name;
343 Dwarf_Addr addr;
344};
345
Masami Hiramatsu016f2622010-03-16 18:05:58 -0400346static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400347{
Masami Hiramatsu378eeaa2010-10-21 19:13:09 +0900348 struct __find_variable_param *fvp = data;
Masami Hiramatsu016f2622010-03-16 18:05:58 -0400349 int tag;
350
351 tag = dwarf_tag(die_mem);
352 if ((tag == DW_TAG_formal_parameter ||
353 tag == DW_TAG_variable) &&
Masami Hiramatsu378eeaa2010-10-21 19:13:09 +0900354 die_compare_name(die_mem, fvp->name))
Masami Hiramatsu016f2622010-03-16 18:05:58 -0400355 return DIE_FIND_CB_FOUND;
356
Masami Hiramatsu378eeaa2010-10-21 19:13:09 +0900357 if (dwarf_haspc(die_mem, fvp->addr))
358 return DIE_FIND_CB_CONTINUE;
359 else
360 return DIE_FIND_CB_SIBLING;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400361}
362
Masami Hiramatsu378eeaa2010-10-21 19:13:09 +0900363/* 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)
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500366{
Masami Hiramatsu378eeaa2010-10-21 19:13:09 +0900367 struct __find_variable_param fvp = { .name = name, .addr = addr};
368
369 return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
Masami Hiramatsu016f2622010-03-16 18:05:58 -0400370 die_mem);
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400371}
372
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400373static 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) &&
Masami Hiramatsu82175632010-07-09 18:29:17 +0900378 die_compare_name(die_mem, name))
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400379 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
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900392/* 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
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400446/*
447 * Probe finder related functions
448 */
449
Srikar Dronamraju0e608362010-07-29 19:43:51 +0530450static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400451{
Srikar Dronamraju0e608362010-07-29 19:43:51 +0530452 struct probe_trace_arg_ref *ref;
453 ref = zalloc(sizeof(struct probe_trace_arg_ref));
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400454 if (ref != NULL)
455 ref->offset = offs;
456 return ref;
457}
458
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900459/*
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)
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400466{
467 Dwarf_Attribute attr;
468 Dwarf_Op *op;
469 size_t nops;
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500470 unsigned int regn;
471 Dwarf_Word offs = 0;
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400472 bool ref = false;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400473 const char *regs;
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400474 int ret;
475
Masami Hiramatsu632941c2010-10-21 19:13:16 +0900476 if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
477 goto static_var;
478
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400479 /* TODO: handle more than 1 exprs */
480 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL ||
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900481 dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0 ||
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400482 nops == 0) {
483 /* TODO: Support const_value */
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400484 return -ENOENT;
485 }
486
487 if (op->atom == DW_OP_addr) {
Masami Hiramatsu632941c2010-10-21 19:13:16 +0900488static_var:
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900489 if (!tvar)
490 return 0;
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400491 /* 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 }
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400502
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400503 /* If this is based on frame buffer, set the offset */
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500504 if (op->atom == DW_OP_fbreg) {
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900505 if (fb_ops == NULL)
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400506 return -ENOTSUP;
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400507 ref = true;
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500508 offs = op->number;
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900509 op = &fb_ops[0];
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500510 }
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400511
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500512 if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
513 regn = op->atom - DW_OP_breg0;
514 offs += op->number;
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400515 ref = true;
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500516 } 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;
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400521 ref = true;
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500522 } else if (op->atom == DW_OP_regx) {
523 regn = op->number;
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400524 } else {
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900525 pr_debug("DW_OP %x is not supported.\n", op->atom);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400526 return -ENOTSUP;
527 }
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400528
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900529 if (!tvar)
530 return 0;
531
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400532 regs = get_arch_regstr(regn);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400533 if (!regs) {
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900534 /* 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);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400537 return -ERANGE;
538 }
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400539
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400540 tvar->value = strdup(regs);
541 if (tvar->value == NULL)
542 return -ENOMEM;
543
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400544 if (ref) {
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400545 tvar->ref = alloc_trace_arg_ref((long)offs);
Masami Hiramatsue334016f12010-04-12 13:17:49 -0400546 if (tvar->ref == NULL)
547 return -ENOMEM;
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400548 }
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400549 return 0;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400550}
551
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400552static int convert_variable_type(Dwarf_Die *vr_die,
Srikar Dronamraju0e608362010-07-29 19:43:51 +0530553 struct probe_trace_arg *tvar,
Masami Hiramatsu73317b92010-05-19 15:57:35 -0400554 const char *cast)
Masami Hiramatsu49849122010-04-12 13:17:15 -0400555{
Srikar Dronamraju0e608362010-07-29 19:43:51 +0530556 struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
Masami Hiramatsu49849122010-04-12 13:17:15 -0400557 Dwarf_Die type;
558 char buf[16];
559 int ret;
560
Masami Hiramatsu73317b92010-05-19 15:57:35 -0400561 /* 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
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400568 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 }
Masami Hiramatsu49849122010-04-12 13:17:15 -0400573
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400574 pr_debug("%s type is %s.\n",
575 dwarf_diename(vr_die), dwarf_diename(&type));
576
Masami Hiramatsu73317b92010-05-19 15:57:35 -0400577 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 */
Srikar Dronamraju0e608362010-07-29 19:43:51 +0530594 *ref_ptr = zalloc(sizeof(struct probe_trace_arg_ref));
Masami Hiramatsu73317b92010-05-19 15:57:35 -0400595 if (*ref_ptr == NULL) {
596 pr_warning("Out of memory error\n");
597 return -ENOMEM;
598 }
599 }
Masami Hiramatsu82175632010-07-09 18:29:17 +0900600 if (!die_compare_name(&type, "char") &&
601 !die_compare_name(&type, "unsigned char")) {
Masami Hiramatsu73317b92010-05-19 15:57:35 -0400602 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
Masami Hiramatsu49849122010-04-12 13:17:15 -0400611 ret = die_get_byte_size(&type) * 8;
612 if (ret) {
613 /* Check the bitwidth */
614 if (ret > MAX_BASIC_TYPE_BITS) {
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400615 pr_info("%s exceeds max-bitwidth."
616 " Cut down to %d bits.\n",
617 dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
Masami Hiramatsu49849122010-04-12 13:17:15 -0400618 ret = MAX_BASIC_TYPE_BITS;
619 }
620
621 ret = snprintf(buf, 16, "%c%d",
622 die_is_signed_type(&type) ? 's' : 'u', ret);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400623 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 }
Masami Hiramatsu73317b92010-05-19 15:57:35 -0400630 tvar->type = strdup(buf);
631 if (tvar->type == NULL)
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400632 return -ENOMEM;
Masami Hiramatsu49849122010-04-12 13:17:15 -0400633 }
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400634 return 0;
Masami Hiramatsu49849122010-04-12 13:17:15 -0400635}
636
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400637static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400638 struct perf_probe_arg_field *field,
Srikar Dronamraju0e608362010-07-29 19:43:51 +0530639 struct probe_trace_arg_ref **ref_ptr,
Masami Hiramatsu49849122010-04-12 13:17:15 -0400640 Dwarf_Die *die_mem)
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400641{
Srikar Dronamraju0e608362010-07-29 19:43:51 +0530642 struct probe_trace_arg_ref *ref = *ref_ptr;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400643 Dwarf_Die type;
644 Dwarf_Word offs;
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400645 int ret, tag;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400646
647 pr_debug("converting %s in %s\n", field->name, varname);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400648 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 }
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400652 pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type));
653 tag = dwarf_tag(&type);
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400654
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400655 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) {
Srikar Dronamraju0e608362010-07-29 19:43:51 +0530668 ref = zalloc(sizeof(struct probe_trace_arg_ref));
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400669 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 */
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400683 if (!field->ref) {
684 pr_err("Semantic error: %s must be referred by '->'\n",
685 field->name);
686 return -EINVAL;
687 }
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400688 /* Get the type pointed by this pointer */
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400689 if (die_get_real_type(&type, &type) == NULL) {
690 pr_warning("Failed to get the type of %s.\n", varname);
691 return -ENOENT;
692 }
Masami Hiramatsu12e5a7a2010-04-02 12:50:53 -0400693 /* Verify it is a data structure */
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400694 if (dwarf_tag(&type) != DW_TAG_structure_type) {
695 pr_warning("%s is not a data structure.\n", varname);
696 return -EINVAL;
697 }
Masami Hiramatsu12e5a7a2010-04-02 12:50:53 -0400698
Srikar Dronamraju0e608362010-07-29 19:43:51 +0530699 ref = zalloc(sizeof(struct probe_trace_arg_ref));
Masami Hiramatsue334016f12010-04-12 13:17:49 -0400700 if (ref == NULL)
701 return -ENOMEM;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400702 if (*ref_ptr)
703 (*ref_ptr)->next = ref;
704 else
705 *ref_ptr = ref;
706 } else {
Masami Hiramatsu12e5a7a2010-04-02 12:50:53 -0400707 /* Verify it is a data structure */
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400708 if (tag != DW_TAG_structure_type) {
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400709 pr_warning("%s is not a data structure.\n", varname);
710 return -EINVAL;
711 }
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400712 if (field->name[0] == '[') {
713 pr_err("Semantic error: %s is not a pointor nor array.",
714 varname);
715 return -EINVAL;
716 }
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400717 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 }
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400727 }
728
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400729 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 }
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400734
735 /* Get the offset of the field */
Masami Hiramatsude1439d2010-04-14 17:44:00 -0300736 ret = die_get_data_member_location(die_mem, &offs);
737 if (ret < 0) {
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400738 pr_warning("Failed to get the offset of %s.\n", field->name);
Masami Hiramatsude1439d2010-04-14 17:44:00 -0300739 return ret;
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400740 }
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400741 ref->offset += (long)offs;
742
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400743next:
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400744 /* Converting next field */
745 if (field->next)
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400746 return convert_variable_fields(die_mem, field->name,
Masami Hiramatsude1439d2010-04-14 17:44:00 -0300747 field->next, &ref, die_mem);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400748 else
749 return 0;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400750}
751
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400752/* Show a variables in kprobe event format */
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400753static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400754{
Masami Hiramatsu49849122010-04-12 13:17:15 -0400755 Dwarf_Die die_mem;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400756 int ret;
757
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400758 pr_debug("Converting variable %s into trace event.\n",
759 dwarf_diename(vr_die));
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500760
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900761 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) {
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400769 ret = convert_variable_fields(vr_die, pf->pvar->var,
770 pf->pvar->field, &pf->tvar->ref,
771 &die_mem);
Masami Hiramatsu49849122010-04-12 13:17:15 -0400772 vr_die = &die_mem;
773 }
Masami Hiramatsu73317b92010-05-19 15:57:35 -0400774 if (ret == 0)
775 ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500776 /* *expr will be cached in libdw. Don't free it. */
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400777 return ret;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400778}
779
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400780/* Find a variable in a subprogram die */
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400781static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400782{
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400783 Dwarf_Die vr_die, *scopes;
Masami Hiramatsu11a1ca32010-04-12 13:17:22 -0400784 char buf[32], *ptr;
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400785 int ret, nscopes;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400786
Masami Hiramatsu367e94c2010-08-27 20:38:59 +0900787 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
Masami Hiramatsu48481932010-04-12 13:16:53 -0400806 if (pf->pvar->name)
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400807 pf->tvar->name = strdup(pf->pvar->name);
Masami Hiramatsu48481932010-04-12 13:16:53 -0400808 else {
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400809 ret = synthesize_perf_probe_arg(pf->pvar, buf, 32);
810 if (ret < 0)
811 return ret;
Masami Hiramatsu11a1ca32010-04-12 13:17:22 -0400812 ptr = strchr(buf, ':'); /* Change type separator to _ */
813 if (ptr)
814 *ptr = '_';
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400815 pf->tvar->name = strdup(buf);
Masami Hiramatsu48481932010-04-12 13:16:53 -0400816 }
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400817 if (pf->tvar->name == NULL)
818 return -ENOMEM;
Masami Hiramatsu48481932010-04-12 13:16:53 -0400819
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400820 pr_debug("Searching '%s' variable in context.\n",
821 pf->pvar->var);
822 /* Search child die for local variables and parameters. */
Masami Hiramatsu378eeaa2010-10-21 19:13:09 +0900823 if (die_find_variable_at(sp_die, pf->pvar->var, pf->addr, &vr_die))
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400824 ret = convert_variable(&vr_die, pf);
825 else {
826 /* Search upper class */
827 nscopes = dwarf_getscopes_die(sp_die, &scopes);
Masami Hiramatsu632941c2010-10-21 19:13:16 +0900828 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)) {
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400835 ret = convert_variable(&vr_die, pf);
Masami Hiramatsu632941c2010-10-21 19:13:16 +0900836 goto found;
837 }
838 }
839 if (scopes)
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400840 free(scopes);
Masami Hiramatsu632941c2010-10-21 19:13:16 +0900841 ret = -ENOENT;
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400842 }
Masami Hiramatsu632941c2010-10-21 19:13:16 +0900843found:
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400844 if (ret < 0)
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400845 pr_warning("Failed to find '%s' in this function.\n",
846 pf->pvar->var);
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400847 return ret;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400848}
849
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900850/* 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)
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400853{
Masami Hiramatsue92b85e2010-02-25 08:35:50 -0500854 Dwarf_Addr eaddr;
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500855 const char *name;
Masami Hiramatsue92b85e2010-02-25 08:35:50 -0500856
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400857 /* Copy the name of probe point */
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500858 name = dwarf_diename(sp_die);
859 if (name) {
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400860 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 }
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900865 tp->symbol = strdup(name);
866 if (tp->symbol == NULL)
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400867 return -ENOMEM;
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900868 tp->offset = (unsigned long)(paddr - eaddr);
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400869 } else
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400870 /* This function has no name. */
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900871 tp->offset = (unsigned long)paddr;
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400872
Masami Hiramatsu04ddd042010-08-27 20:38:53 +0900873 /* Return probe must be on the head of a subprogram */
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900874 if (retprobe) {
875 if (eaddr != paddr) {
Masami Hiramatsu04ddd042010-08-27 20:38:53 +0900876 pr_warning("Return probe must be on the head of"
877 " a real function\n");
878 return -EINVAL;
879 }
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900880 tp->retprobe = true;
Masami Hiramatsu04ddd042010-08-27 20:38:53 +0900881 }
882
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900883 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 }
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400904
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500905 /* Get the frame base attribute/ops */
906 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
Masami Hiramatsud0cb4262010-03-15 13:02:35 -0400907 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
Masami Hiramatsua34a9852010-04-12 13:17:29 -0400908 if (ret <= 0 || nops == 0) {
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500909 pf->fb_ops = NULL;
Masami Hiramatsu7752f1b2010-05-10 13:12:07 -0400910#if _ELFUTILS_PREREQ(0, 142)
Masami Hiramatsua34a9852010-04-12 13:17:29 -0400911 } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
912 pf->cfi != NULL) {
913 Dwarf_Frame *frame;
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400914 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 }
Masami Hiramatsu7752f1b2010-05-10 13:12:07 -0400920#endif
Masami Hiramatsua34a9852010-04-12 13:17:29 -0400921 }
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500922
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900923 /* Call finder's callback handler */
924 ret = pf->callback(sp_die, pf);
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500925
926 /* *pf->fb_ops will be cached in libdw. Don't free it. */
927 pf->fb_ops = NULL;
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900928
929 return ret;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400930}
931
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400932/* Find probe point from its line number */
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400933static int find_probe_point_by_line(struct probe_finder *pf)
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400934{
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500935 Dwarf_Lines *lines;
936 Dwarf_Line *line;
937 size_t nlines, i;
Masami Hiramatsue92b85e2010-02-25 08:35:50 -0500938 Dwarf_Addr addr;
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500939 int lineno;
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400940 int ret = 0;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400941
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400942 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
943 pr_warning("No source lines found in this CU.\n");
944 return -ENOENT;
945 }
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400946
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400947 for (i = 0; i < nlines && ret == 0; i++) {
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500948 line = dwarf_onesrcline(lines, i);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400949 if (dwarf_lineno(line, &lineno) != 0 ||
950 lineno != pf->lno)
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400951 continue;
952
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500953 /* TODO: Get fileno from line, but how? */
954 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
955 continue;
Masami Hiramatsub0ef0732009-10-27 16:43:19 -0400956
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400957 if (dwarf_lineaddr(line, &addr) != 0) {
958 pr_warning("Failed to get the address of the line.\n");
959 return -ENOENT;
960 }
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500961 pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
962 (int)i, lineno, (uintmax_t)addr);
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400963 pf->addr = addr;
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500964
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900965 ret = call_probe_finder(NULL, pf);
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400966 /* Continuing, because target line might be inlined. */
967 }
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400968 return ret;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400969}
970
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500971/* 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;
Arnaldo Carvalho de Melob448c4b2010-05-18 23:04:28 -0300976 int fd, line, nlines = -1;
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500977 struct stat st;
978
979 fd = open(fname, O_RDONLY);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400980 if (fd < 0) {
981 pr_warning("Failed to open %s: %s\n", fname, strerror(-fd));
Arnaldo Carvalho de Melob448c4b2010-05-18 23:04:28 -0300982 return -errno;
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400983 }
984
Arnaldo Carvalho de Melob448c4b2010-05-18 23:04:28 -0300985 if (fstat(fd, &st) < 0) {
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400986 pr_warning("Failed to get the size of %s: %s\n",
987 fname, strerror(errno));
Arnaldo Carvalho de Melob448c4b2010-05-18 23:04:28 -0300988 nlines = -errno;
989 goto out_close;
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400990 }
Arnaldo Carvalho de Melob448c4b2010-05-18 23:04:28 -0300991
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) {
Masami Hiramatsub55a87a2010-04-12 13:17:35 -0400997 pr_warning("Failed to read %s: %s\n", fname, strerror(errno));
Arnaldo Carvalho de Melob448c4b2010-05-18 23:04:28 -0300998 nlines = -errno;
999 goto out_free_fbuf;
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001000 }
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001001 fbuf[st.st_size] = '\n'; /* Dummy line */
1002 fbuf[st.st_size + 1] = '\0';
1003 p1 = fbuf;
1004 line = 1;
Arnaldo Carvalho de Melob448c4b2010-05-18 23:04:28 -03001005 nlines = 0;
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001006 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 }
Arnaldo Carvalho de Melob448c4b2010-05-18 23:04:28 -03001015out_free_fbuf:
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001016 free(fbuf);
Arnaldo Carvalho de Melob448c4b2010-05-18 23:04:28 -03001017out_close:
1018 close(fd);
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001019 return nlines;
1020}
1021
1022/* Find probe points from lazy pattern */
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001023static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001024{
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;
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001031 int ret = 0;
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001032
1033 if (list_empty(&pf->lcache)) {
1034 /* Matching lazy line pattern */
1035 ret = find_lazy_match_lines(&pf->lcache, pf->fname,
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001036 pf->pev->point.lazy_line);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001037 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;
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001042 }
1043
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001044 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++) {
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001050 line = dwarf_onesrcline(lines, i);
1051
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001052 if (dwarf_lineno(line, &lineno) != 0 ||
1053 !line_list__has_line(&pf->lcache, lineno))
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001054 continue;
1055
1056 /* TODO: Get fileno from line, but how? */
1057 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
1058 continue;
1059
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001060 if (dwarf_lineaddr(line, &addr) != 0) {
1061 pr_debug("Failed to get the address of line %d.\n",
1062 lineno);
1063 continue;
1064 }
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001065 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? */
Masami Hiramatsu95a3e4c2010-03-16 18:05:51 -04001070 if (die_find_inlinefunc(sp_die, addr, &die_mem))
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001071 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
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001078 ret = call_probe_finder(sp_die, pf);
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001079 /* Continuing, because target line might be inlined. */
1080 }
1081 /* TODO: deallocate lines, but how? */
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001082 return ret;
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001083}
1084
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001085/* Callback parameter with return value */
1086struct dwarf_callback_param {
1087 void *data;
1088 int retval;
1089};
1090
Masami Hiramatsue92b85e2010-02-25 08:35:50 -05001091static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001092{
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001093 struct dwarf_callback_param *param = data;
1094 struct probe_finder *pf = param->data;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001095 struct perf_probe_point *pp = &pf->pev->point;
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001096 Dwarf_Addr addr;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001097
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001098 if (pp->lazy_line)
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001099 param->retval = find_probe_point_lazy(in_die, pf);
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001100 else {
1101 /* Get probe address */
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001102 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;
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001109 pf->addr += pp->offset;
1110 pr_debug("found inline addr: 0x%jx\n",
1111 (uintmax_t)pf->addr);
Masami Hiramatsue92b85e2010-02-25 08:35:50 -05001112
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001113 param->retval = call_probe_finder(in_die, pf);
Masami Hiramatsu5d1ee042010-04-21 15:56:32 -04001114 if (param->retval < 0)
1115 return DWARF_CB_ABORT;
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001116 }
1117
Masami Hiramatsue92b85e2010-02-25 08:35:50 -05001118 return DWARF_CB_OK;
1119}
1120
1121/* Search function from function name */
1122static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
1123{
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001124 struct dwarf_callback_param *param = data;
1125 struct probe_finder *pf = param->data;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001126 struct perf_probe_point *pp = &pf->pev->point;
Masami Hiramatsue92b85e2010-02-25 08:35:50 -05001127
1128 /* Check tag and diename */
1129 if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
Masami Hiramatsu82175632010-07-09 18:29:17 +09001130 !die_compare_name(sp_die, pp->function))
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001131 return DWARF_CB_OK;
Masami Hiramatsue92b85e2010-02-25 08:35:50 -05001132
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001133 pf->fname = dwarf_decl_file(sp_die);
Masami Hiramatsue92b85e2010-02-25 08:35:50 -05001134 if (pp->line) { /* Function relative line */
Masami Hiramatsue92b85e2010-02-25 08:35:50 -05001135 dwarf_decl_line(sp_die, &pf->lno);
1136 pf->lno += pp->line;
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001137 param->retval = find_probe_point_by_line(pf);
Masami Hiramatsue92b85e2010-02-25 08:35:50 -05001138 } else if (!dwarf_func_inline(sp_die)) {
1139 /* Real function */
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001140 if (pp->lazy_line)
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001141 param->retval = find_probe_point_lazy(sp_die, pf);
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001142 else {
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001143 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 }
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001149 pf->addr += pp->offset;
1150 /* TODO: Check the address in this function */
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001151 param->retval = call_probe_finder(sp_die, pf);
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001152 }
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001153 } else {
1154 struct dwarf_callback_param _param = {.data = (void *)pf,
1155 .retval = 0};
Masami Hiramatsue92b85e2010-02-25 08:35:50 -05001156 /* Inlined function: search instances */
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001157 dwarf_func_inline_instances(sp_die, probe_point_inline_cb,
1158 &_param);
1159 param->retval = _param.retval;
1160 }
Masami Hiramatsue92b85e2010-02-25 08:35:50 -05001161
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001162 return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001163}
1164
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001165static int find_probe_point_by_func(struct probe_finder *pf)
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001166{
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001167 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;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001171}
1172
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001173/* Find probe points from debuginfo */
1174static int find_probes(int fd, struct probe_finder *pf)
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001175{
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001176 struct perf_probe_point *pp = &pf->pev->point;
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001177 Dwarf_Off off, noff;
1178 size_t cuhl;
1179 Dwarf_Die *diep;
1180 Dwarf *dbg;
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001181 int ret = 0;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001182
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001183 dbg = dwarf_begin(fd, DWARF_C_READ);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001184 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 }
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001189
Masami Hiramatsu7752f1b2010-05-10 13:12:07 -04001190#if _ELFUTILS_PREREQ(0, 142)
Masami Hiramatsua34a9852010-04-12 13:17:29 -04001191 /* Get the call frame information from this dwarf */
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001192 pf->cfi = dwarf_getcfi(dbg);
Masami Hiramatsu7752f1b2010-05-10 13:12:07 -04001193#endif
Masami Hiramatsua34a9852010-04-12 13:17:29 -04001194
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001195 off = 0;
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001196 line_list__init(&pf->lcache);
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001197 /* Loop on CUs (Compilation Unit) */
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001198 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) &&
1199 ret >= 0) {
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001200 /* Get the DIE(Debugging Information Entry) of this CU */
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001201 diep = dwarf_offdie(dbg, off + cuhl, &pf->cu_die);
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001202 if (!diep)
1203 continue;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001204
1205 /* Check if target file is included. */
1206 if (pp->file)
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001207 pf->fname = cu_find_realpath(&pf->cu_die, pp->file);
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001208 else
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001209 pf->fname = NULL;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001210
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001211 if (!pp->file || pf->fname) {
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001212 if (pp->function)
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001213 ret = find_probe_point_by_func(pf);
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001214 else if (pp->lazy_line)
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001215 ret = find_probe_point_lazy(NULL, pf);
Masami Hiramatsub0ef0732009-10-27 16:43:19 -04001216 else {
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001217 pf->lno = pp->line;
1218 ret = find_probe_point_by_line(pf);
Masami Hiramatsub0ef0732009-10-27 16:43:19 -04001219 }
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001220 }
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001221 off = noff;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001222 }
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001223 line_list__free(&pf->lcache);
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001224 dwarf_end(dbg);
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001225
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001226 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);
Masami Hiramatsufb8c5a52010-10-21 19:13:35 +09001315 pr_debug2("Add new var: %s\n", buf);
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001316 if (ret > 0)
1317 strlist__add(vl->vars, buf);
1318 }
1319 }
1320
Masami Hiramatsufb8c5a52010-10-21 19:13:35 +09001321 if (af->child && dwarf_haspc(die_mem, af->pf.addr))
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001322 return DIE_FIND_CB_CONTINUE;
1323 else
1324 return DIE_FIND_CB_SIBLING;
1325}
1326
1327/* Add a found vars into available variables list */
1328static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
1329{
1330 struct available_var_finder *af =
1331 container_of(pf, struct available_var_finder, pf);
1332 struct variable_list *vl;
Masami Hiramatsufb8c5a52010-10-21 19:13:35 +09001333 Dwarf_Die die_mem, *scopes = NULL;
1334 int ret, nscopes;
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001335
1336 /* Check number of tevs */
1337 if (af->nvls == af->max_vls) {
1338 pr_warning("Too many( > %d) probe point found.\n", af->max_vls);
1339 return -ERANGE;
1340 }
1341 vl = &af->vls[af->nvls++];
1342
1343 ret = convert_to_trace_point(sp_die, pf->addr, pf->pev->point.retprobe,
1344 &vl->point);
1345 if (ret < 0)
1346 return ret;
1347
1348 pr_debug("Probe point found: %s+%lu\n", vl->point.symbol,
1349 vl->point.offset);
1350
1351 /* Find local variables */
1352 vl->vars = strlist__new(true, NULL);
1353 if (vl->vars == NULL)
1354 return -ENOMEM;
Masami Hiramatsufb8c5a52010-10-21 19:13:35 +09001355 af->child = true;
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001356 die_find_child(sp_die, collect_variables_cb, (void *)af, &die_mem);
1357
Masami Hiramatsufb8c5a52010-10-21 19:13:35 +09001358 /* Find external variables */
1359 if (!af->externs)
1360 goto out;
1361 /* Don't need to search child DIE for externs. */
1362 af->child = false;
1363 nscopes = dwarf_getscopes_die(sp_die, &scopes);
1364 while (nscopes-- > 1)
1365 die_find_child(&scopes[nscopes], collect_variables_cb,
1366 (void *)af, &die_mem);
1367 if (scopes)
1368 free(scopes);
1369
1370out:
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001371 if (strlist__empty(vl->vars)) {
1372 strlist__delete(vl->vars);
1373 vl->vars = NULL;
1374 }
1375
1376 return ret;
1377}
1378
1379/* Find available variables at given probe point */
1380int find_available_vars_at(int fd, struct perf_probe_event *pev,
Masami Hiramatsufb8c5a52010-10-21 19:13:35 +09001381 struct variable_list **vls, int max_vls,
1382 bool externs)
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001383{
1384 struct available_var_finder af = {
1385 .pf = {.pev = pev, .callback = add_available_vars},
Masami Hiramatsufb8c5a52010-10-21 19:13:35 +09001386 .max_vls = max_vls, .externs = externs};
Masami Hiramatsucf6eb482010-10-21 19:13:23 +09001387 int ret;
1388
1389 /* Allocate result vls array */
1390 *vls = zalloc(sizeof(struct variable_list) * max_vls);
1391 if (*vls == NULL)
1392 return -ENOMEM;
1393
1394 af.vls = *vls;
1395 af.nvls = 0;
1396
1397 ret = find_probes(fd, &af.pf);
1398 if (ret < 0) {
1399 /* Free vlist for error */
1400 while (af.nvls--) {
1401 if (af.vls[af.nvls].point.symbol)
1402 free(af.vls[af.nvls].point.symbol);
1403 if (af.vls[af.nvls].vars)
1404 strlist__delete(af.vls[af.nvls].vars);
1405 }
1406 free(af.vls);
1407 *vls = NULL;
1408 return ret;
1409 }
1410
1411 return (ret < 0) ? ret : af.nvls;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001412}
1413
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001414/* Reverse search */
1415int find_perf_probe_point(int fd, unsigned long addr,
1416 struct perf_probe_point *ppt)
1417{
1418 Dwarf_Die cudie, spdie, indie;
1419 Dwarf *dbg;
1420 Dwarf_Line *line;
1421 Dwarf_Addr laddr, eaddr;
1422 const char *tmp;
1423 int lineno, ret = 0;
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001424 bool found = false;
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001425
1426 dbg = dwarf_begin(fd, DWARF_C_READ);
1427 if (!dbg)
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001428 return -EBADF;
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001429
1430 /* Find cu die */
Masami Hiramatsu75ec5a22010-04-02 12:50:59 -04001431 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) {
1432 ret = -EINVAL;
1433 goto end;
1434 }
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001435
1436 /* Find a corresponding line */
1437 line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr);
1438 if (line) {
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001439 if (dwarf_lineaddr(line, &laddr) == 0 &&
1440 (Dwarf_Addr)addr == laddr &&
1441 dwarf_lineno(line, &lineno) == 0) {
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001442 tmp = dwarf_linesrc(line, NULL, NULL);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001443 if (tmp) {
1444 ppt->line = lineno;
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001445 ppt->file = strdup(tmp);
1446 if (ppt->file == NULL) {
1447 ret = -ENOMEM;
1448 goto end;
1449 }
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001450 found = true;
1451 }
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001452 }
1453 }
1454
1455 /* Find a corresponding function */
1456 if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) {
1457 tmp = dwarf_diename(&spdie);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001458 if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0)
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001459 goto end;
1460
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001461 if (ppt->line) {
1462 if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
1463 &indie)) {
1464 /* addr in an inline function */
1465 tmp = dwarf_diename(&indie);
1466 if (!tmp)
1467 goto end;
1468 ret = dwarf_decl_line(&indie, &lineno);
1469 } else {
1470 if (eaddr == addr) { /* Function entry */
1471 lineno = ppt->line;
1472 ret = 0;
1473 } else
1474 ret = dwarf_decl_line(&spdie, &lineno);
1475 }
1476 if (ret == 0) {
1477 /* Make a relative line number */
1478 ppt->line -= lineno;
1479 goto found;
1480 }
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001481 }
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001482 /* We don't have a line number, let's use offset */
1483 ppt->offset = addr - (unsigned long)eaddr;
1484found:
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001485 ppt->function = strdup(tmp);
1486 if (ppt->function == NULL) {
1487 ret = -ENOMEM;
1488 goto end;
1489 }
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001490 found = true;
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001491 }
1492
1493end:
1494 dwarf_end(dbg);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001495 if (ret >= 0)
1496 ret = found ? 1 : 0;
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001497 return ret;
1498}
1499
Masami Hiramatsuf6c903f2010-04-14 18:40:07 -04001500/* Add a line and store the src path */
1501static int line_range_add_line(const char *src, unsigned int lineno,
1502 struct line_range *lr)
1503{
Masami Hiramatsu7cf0b792010-07-09 18:28:59 +09001504 /* Copy source path */
Masami Hiramatsuf6c903f2010-04-14 18:40:07 -04001505 if (!lr->path) {
Masami Hiramatsu7cf0b792010-07-09 18:28:59 +09001506 lr->path = strdup(src);
1507 if (lr->path == NULL)
1508 return -ENOMEM;
Masami Hiramatsuf6c903f2010-04-14 18:40:07 -04001509 }
1510 return line_list__add_line(&lr->line_list, lineno);
1511}
1512
1513/* Search function declaration lines */
1514static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data)
1515{
1516 struct dwarf_callback_param *param = data;
1517 struct line_finder *lf = param->data;
1518 const char *src;
1519 int lineno;
1520
1521 src = dwarf_decl_file(sp_die);
1522 if (src && strtailcmp(src, lf->fname) != 0)
1523 return DWARF_CB_OK;
1524
1525 if (dwarf_decl_line(sp_die, &lineno) != 0 ||
1526 (lf->lno_s > lineno || lf->lno_e < lineno))
1527 return DWARF_CB_OK;
1528
1529 param->retval = line_range_add_line(src, lineno, lf->lr);
Masami Hiramatsu5d1ee042010-04-21 15:56:32 -04001530 if (param->retval < 0)
1531 return DWARF_CB_ABORT;
Masami Hiramatsuf6c903f2010-04-14 18:40:07 -04001532 return DWARF_CB_OK;
1533}
1534
1535static int find_line_range_func_decl_lines(struct line_finder *lf)
1536{
1537 struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
1538 dwarf_getfuncs(&lf->cu_die, line_range_funcdecl_cb, &param, 0);
1539 return param.retval;
1540}
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001541
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001542/* Find line range from its line number */
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001543static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001544{
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001545 Dwarf_Lines *lines;
1546 Dwarf_Line *line;
1547 size_t nlines, i;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001548 Dwarf_Addr addr;
Masami Hiramatsuf6c903f2010-04-14 18:40:07 -04001549 int lineno, ret = 0;
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001550 const char *src;
Masami Hiramatsu161a26b2010-02-25 08:35:57 -05001551 Dwarf_Die die_mem;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001552
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001553 line_list__init(&lf->lr->line_list);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001554 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
1555 pr_warning("No source lines found in this CU.\n");
1556 return -ENOENT;
1557 }
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001558
Masami Hiramatsuf6c903f2010-04-14 18:40:07 -04001559 /* Search probable lines on lines list */
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001560 for (i = 0; i < nlines; i++) {
1561 line = dwarf_onesrcline(lines, i);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001562 if (dwarf_lineno(line, &lineno) != 0 ||
1563 (lf->lno_s > lineno || lf->lno_e < lineno))
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001564 continue;
1565
Masami Hiramatsu161a26b2010-02-25 08:35:57 -05001566 if (sp_die) {
1567 /* Address filtering 1: does sp_die include addr? */
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001568 if (dwarf_lineaddr(line, &addr) != 0 ||
1569 !dwarf_haspc(sp_die, addr))
Masami Hiramatsu161a26b2010-02-25 08:35:57 -05001570 continue;
1571
1572 /* Address filtering 2: No child include addr? */
Masami Hiramatsu95a3e4c2010-03-16 18:05:51 -04001573 if (die_find_inlinefunc(sp_die, addr, &die_mem))
Masami Hiramatsu161a26b2010-02-25 08:35:57 -05001574 continue;
1575 }
1576
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001577 /* TODO: Get fileno from line, but how? */
1578 src = dwarf_linesrc(line, NULL, NULL);
1579 if (strtailcmp(src, lf->fname) != 0)
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001580 continue;
1581
Masami Hiramatsuf6c903f2010-04-14 18:40:07 -04001582 ret = line_range_add_line(src, lineno, lf->lr);
1583 if (ret < 0)
1584 return ret;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001585 }
Masami Hiramatsuf6c903f2010-04-14 18:40:07 -04001586
1587 /*
1588 * Dwarf lines doesn't include function declarations. We have to
1589 * check functions list or given function.
1590 */
1591 if (sp_die) {
1592 src = dwarf_decl_file(sp_die);
1593 if (src && dwarf_decl_line(sp_die, &lineno) == 0 &&
1594 (lf->lno_s <= lineno && lf->lno_e >= lineno))
1595 ret = line_range_add_line(src, lineno, lf->lr);
1596 } else
1597 ret = find_line_range_func_decl_lines(lf);
1598
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001599 /* Update status */
Masami Hiramatsuf6c903f2010-04-14 18:40:07 -04001600 if (ret >= 0)
1601 if (!list_empty(&lf->lr->line_list))
1602 ret = lf->found = 1;
1603 else
1604 ret = 0; /* Lines are not found */
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001605 else {
1606 free(lf->lr->path);
1607 lf->lr->path = NULL;
1608 }
Masami Hiramatsuf6c903f2010-04-14 18:40:07 -04001609 return ret;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001610}
1611
Masami Hiramatsu161a26b2010-02-25 08:35:57 -05001612static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
1613{
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001614 struct dwarf_callback_param *param = data;
1615
1616 param->retval = find_line_range_by_line(in_die, param->data);
Masami Hiramatsu161a26b2010-02-25 08:35:57 -05001617 return DWARF_CB_ABORT; /* No need to find other instances */
1618}
1619
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001620/* Search function from function name */
Masami Hiramatsue92b85e2010-02-25 08:35:50 -05001621static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001622{
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001623 struct dwarf_callback_param *param = data;
1624 struct line_finder *lf = param->data;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001625 struct line_range *lr = lf->lr;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001626
Masami Hiramatsue92b85e2010-02-25 08:35:50 -05001627 if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
Masami Hiramatsu82175632010-07-09 18:29:17 +09001628 die_compare_name(sp_die, lr->function)) {
Masami Hiramatsue92b85e2010-02-25 08:35:50 -05001629 lf->fname = dwarf_decl_file(sp_die);
1630 dwarf_decl_line(sp_die, &lr->offset);
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001631 pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001632 lf->lno_s = lr->offset + lr->start;
Masami Hiramatsud3b63d72010-04-14 18:39:42 -04001633 if (lf->lno_s < 0) /* Overflow */
1634 lf->lno_s = INT_MAX;
1635 lf->lno_e = lr->offset + lr->end;
1636 if (lf->lno_e < 0) /* Overflow */
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001637 lf->lno_e = INT_MAX;
Masami Hiramatsud3b63d72010-04-14 18:39:42 -04001638 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001639 lr->start = lf->lno_s;
1640 lr->end = lf->lno_e;
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001641 if (dwarf_func_inline(sp_die)) {
1642 struct dwarf_callback_param _param;
1643 _param.data = (void *)lf;
1644 _param.retval = 0;
Masami Hiramatsu161a26b2010-02-25 08:35:57 -05001645 dwarf_func_inline_instances(sp_die,
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001646 line_range_inline_cb,
1647 &_param);
1648 param->retval = _param.retval;
1649 } else
1650 param->retval = find_line_range_by_line(sp_die, lf);
1651 return DWARF_CB_ABORT;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001652 }
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001653 return DWARF_CB_OK;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001654}
1655
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001656static int find_line_range_by_func(struct line_finder *lf)
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001657{
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001658 struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
1659 dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
1660 return param.retval;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001661}
1662
1663int find_line_range(int fd, struct line_range *lr)
1664{
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001665 struct line_finder lf = {.lr = lr, .found = 0};
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001666 int ret = 0;
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001667 Dwarf_Off off = 0, noff;
1668 size_t cuhl;
1669 Dwarf_Die *diep;
1670 Dwarf *dbg;
Masami Hiramatsu6a330a32010-07-09 18:29:11 +09001671 const char *comp_dir;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001672
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001673 dbg = dwarf_begin(fd, DWARF_C_READ);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001674 if (!dbg) {
1675 pr_warning("No dwarf info found in the vmlinux - "
1676 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1677 return -EBADF;
1678 }
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001679
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001680 /* Loop on CUs (Compilation Unit) */
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001681 while (!lf.found && ret >= 0) {
1682 if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0)
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001683 break;
1684
1685 /* Get the DIE(Debugging Information Entry) of this CU */
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001686 diep = dwarf_offdie(dbg, off + cuhl, &lf.cu_die);
1687 if (!diep)
1688 continue;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001689
1690 /* Check if target file is included. */
1691 if (lr->file)
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001692 lf.fname = cu_find_realpath(&lf.cu_die, lr->file);
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001693 else
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001694 lf.fname = 0;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001695
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001696 if (!lr->file || lf.fname) {
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001697 if (lr->function)
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001698 ret = find_line_range_by_func(&lf);
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001699 else {
1700 lf.lno_s = lr->start;
Masami Hiramatsud3b63d72010-04-14 18:39:42 -04001701 lf.lno_e = lr->end;
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001702 ret = find_line_range_by_line(NULL, &lf);
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001703 }
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001704 }
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001705 off = noff;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001706 }
Masami Hiramatsu6a330a32010-07-09 18:29:11 +09001707
1708 /* Store comp_dir */
1709 if (lf.found) {
1710 comp_dir = cu_get_comp_dir(&lf.cu_die);
1711 if (comp_dir) {
1712 lr->comp_dir = strdup(comp_dir);
1713 if (!lr->comp_dir)
1714 ret = -ENOMEM;
1715 }
1716 }
1717
Masami Hiramatsu7cf0b792010-07-09 18:28:59 +09001718 pr_debug("path: %s\n", lr->path);
Masami Hiramatsu804b3602010-02-25 08:35:42 -05001719 dwarf_end(dbg);
Masami Hiramatsub55a87a2010-04-12 13:17:35 -04001720
1721 return (ret < 0) ? ret : lf.found;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001722}
1723