Commit 367e94c10092469c896a226a77ef13cf6da757e4

Authored by Masami Hiramatsu
Committed by Arnaldo Carvalho de Melo
1 parent 04ddd04b04

perf probe: Fix handling of arguments names

Don't make argument names from raw parameters (means the parameters are written
in kprobe-tracer syntax), because the argument syntax may include special
characters.  Just leave it, then kprobe-tracer gives a new name.

Reported-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <20100827113859.22882.75598.stgit@ltc236.sdl.hitachi.co.jp>
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

Showing 1 changed file with 19 additions and 13 deletions Inline Diff

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