aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-finder.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/probe-finder.c')
-rw-r--r--tools/perf/util/probe-finder.c136
1 files changed, 80 insertions, 56 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index c91a9605c162..3942e14e95cf 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -186,6 +186,62 @@ static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
186 return src; 186 return src;
187} 187}
188 188
189/* Compare diename and tname */
190static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
191{
192 const char *name;
193 name = dwarf_diename(dw_die);
194 DIE_IF(name == NULL);
195 return strcmp(tname, name);
196}
197
198/* Get entry pc(or low pc, 1st entry of ranges) of the die */
199static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die)
200{
201 Dwarf_Addr epc;
202 int ret;
203
204 ret = dwarf_entrypc(dw_die, &epc);
205 DIE_IF(ret == -1);
206 return epc;
207}
208
209/* Return values for die_find callbacks */
210enum {
211 DIE_FIND_CB_FOUND = 0, /* End of Search */
212 DIE_FIND_CB_CHILD = 1, /* Search only children */
213 DIE_FIND_CB_SIBLING = 2, /* Search only siblings */
214 DIE_FIND_CB_CONTINUE = 3, /* Search children and siblings */
215};
216
217/* Search a child die */
218static Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
219 int (*callback)(Dwarf_Die *, void *),
220 void *data, Dwarf_Die *die_mem)
221{
222 Dwarf_Die child_die;
223 int ret;
224
225 ret = dwarf_child(rt_die, die_mem);
226 if (ret != 0)
227 return NULL;
228
229 do {
230 ret = callback(die_mem, data);
231 if (ret == DIE_FIND_CB_FOUND)
232 return die_mem;
233
234 if ((ret & DIE_FIND_CB_CHILD) &&
235 die_find_child(die_mem, callback, data, &child_die)) {
236 memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
237 return die_mem;
238 }
239 } while ((ret & DIE_FIND_CB_SIBLING) &&
240 dwarf_siblingof(die_mem, die_mem) == 0);
241
242 return NULL;
243}
244
189struct __addr_die_search_param { 245struct __addr_die_search_param {
190 Dwarf_Addr addr; 246 Dwarf_Addr addr;
191 Dwarf_Die *die_mem; 247 Dwarf_Die *die_mem;
@@ -217,77 +273,45 @@ static Dwarf_Die *die_find_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr,
217 return die_mem; 273 return die_mem;
218} 274}
219 275
220/* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */ 276/* die_find callback for inline function search */
221static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, 277static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
222 Dwarf_Die *die_mem)
223{ 278{
224 Dwarf_Die child_die; 279 Dwarf_Addr *addr = data;
225 int ret;
226 280
227 ret = dwarf_child(sp_die, die_mem); 281 if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
228 if (ret != 0) 282 dwarf_haspc(die_mem, *addr))
229 return NULL; 283 return DIE_FIND_CB_FOUND;
230
231 do {
232 if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
233 dwarf_haspc(die_mem, addr))
234 return die_mem;
235 284
236 if (die_find_inlinefunc(die_mem, addr, &child_die)) { 285 return DIE_FIND_CB_CONTINUE;
237 memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
238 return die_mem;
239 }
240 } while (dwarf_siblingof(die_mem, die_mem) == 0);
241
242 return NULL;
243} 286}
244 287
245/* Compare diename and tname */ 288/* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */
246static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) 289static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
290 Dwarf_Die *die_mem)
247{ 291{
248 const char *name; 292 return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
249 name = dwarf_diename(dw_die);
250 DIE_IF(name == NULL);
251 return strcmp(tname, name);
252} 293}
253 294
254/* Get entry pc(or low pc, 1st entry of ranges) of the die */ 295static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
255static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die)
256{ 296{
257 Dwarf_Addr epc; 297 const char *name = data;
258 int ret; 298 int tag;
259 299
260 ret = dwarf_entrypc(dw_die, &epc); 300 tag = dwarf_tag(die_mem);
261 DIE_IF(ret == -1); 301 if ((tag == DW_TAG_formal_parameter ||
262 return epc; 302 tag == DW_TAG_variable) &&
303 (die_compare_name(die_mem, name) == 0))
304 return DIE_FIND_CB_FOUND;
305
306 return DIE_FIND_CB_CONTINUE;
263} 307}
264 308
265/* Get a variable die */ 309/* Find a variable called 'name' */
266static Dwarf_Die *die_find_variable(Dwarf_Die *sp_die, const char *name, 310static Dwarf_Die *die_find_variable(Dwarf_Die *sp_die, const char *name,
267 Dwarf_Die *die_mem) 311 Dwarf_Die *die_mem)
268{ 312{
269 Dwarf_Die child_die; 313 return die_find_child(sp_die, __die_find_variable_cb, (void *)name,
270 int tag; 314 die_mem);
271 int ret;
272
273 ret = dwarf_child(sp_die, die_mem);
274 if (ret != 0)
275 return NULL;
276
277 do {
278 tag = dwarf_tag(die_mem);
279 if ((tag == DW_TAG_formal_parameter ||
280 tag == DW_TAG_variable) &&
281 (die_compare_name(die_mem, name) == 0))
282 return die_mem;
283
284 if (die_find_variable(die_mem, name, &child_die)) {
285 memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
286 return die_mem;
287 }
288 } while (dwarf_siblingof(die_mem, die_mem) == 0);
289
290 return NULL;
291} 315}
292 316
293/* 317/*