Commit db0d2c6420eeb8fd669bac84d72f1ab828bbaa64

Authored by Masami Hiramatsu
Committed by Arnaldo Carvalho de Melo
1 parent f182e3e13c

perf probe: Search concrete out-of-line instances

gcc 4.6 generates a concrete out-of-line instance when there is a
function which is implicitly inlined somewhere but also has its own
instance. The concrete out-of-line instance means that it has an
abstract origin of the function which is referred by not only
inlined-subroutines but also a concrete subprogram.

Since current dwarf_func_inline_instances() can find only instances of
inlined-subroutines, this introduces new die_walk_instances() to find
both of subprogram and inlined-subroutines.

e.g. without this,
Available variables at sched_group_rt_period
        @<cpu_rt_period_read_uint+9>
                struct task_group*      tg

perf probe failed to find actual subprogram instance of
sched_group_rt_period().

With this,

Available variables at sched_group_rt_period
        @<cpu_rt_period_read_uint+9>
                struct task_group*      tg
        @<sched_group_rt_period+0>
                struct task_group*      tg

Now it found the sched_group_rt_period() itself.

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: yrl.pp-manager.tt@hitachi.com
Link: http://lkml.kernel.org/r/20110811110311.19900.63997.stgit@fedora15
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

Showing 3 changed files with 83 additions and 35 deletions Inline Diff

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