Blame view

tools/perf/util/probe-finder.c 46.5 KB
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  /*
   * probe-finder.c : C expression to kprobe event converter
   *
   * Written by Masami Hiramatsu <mhiramat@redhat.com>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   *
   */
fd20e8111   Arnaldo Carvalho de Melo   perf tools: Inclu...
21
  #include <inttypes.h>
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
22
23
24
25
26
27
28
  #include <sys/utsname.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <fcntl.h>
  #include <errno.h>
  #include <stdio.h>
  #include <unistd.h>
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
29
30
31
  #include <stdlib.h>
  #include <string.h>
  #include <stdarg.h>
cd932c593   Ian Munsie   perf: Move arch s...
32
  #include <dwarf-regs.h>
074fc0e4b   Masami Hiramatsu   perf: Use die() f...
33

124bb83cd   Masami Hiramatsu   perf probe: Add b...
34
  #include <linux/bitops.h>
89c69c0ee   Masami Hiramatsu   perf: Use eprintf...
35
  #include "event.h"
a15ad2f53   Masami Hiramatsu   perf probe: Suppo...
36
  #include "dso.h"
89c69c0ee   Masami Hiramatsu   perf: Use eprintf...
37
  #include "debug.h"
5a62257a3   Masami Hiramatsu   perf probe: Repla...
38
  #include "intlist.h"
074fc0e4b   Masami Hiramatsu   perf: Use die() f...
39
  #include "util.h"
8ec20b176   Arnaldo Carvalho de Melo   perf str{filter,l...
40
  #include "strlist.h"
9ed7e1b85   Chase Douglas   perf probe: Add k...
41
  #include "symbol.h"
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
42
  #include "probe-finder.h"
180b20616   Masami Hiramatsu   perf probe: Add s...
43
  #include "probe-file.h"
a067558e2   Arnaldo Carvalho de Melo   perf tools: Move ...
44
  #include "string2.h"
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
45

4984912eb   Masami Hiramatsu   perf probe: Query...
46
47
  /* Kprobe tracer basic type is up to u64 */
  #define MAX_BASIC_TYPE_BITS	64
469b9b884   Masami Hiramatsu   perf probe: Add b...
48
  /* Dwarf FL wrappers */
469b9b884   Masami Hiramatsu   perf probe: Add b...
49
50
51
52
53
54
55
56
57
58
59
  static char *debuginfo_path;	/* Currently dummy */
  
  static const Dwfl_Callbacks offline_callbacks = {
  	.find_debuginfo = dwfl_standard_find_debuginfo,
  	.debuginfo_path = &debuginfo_path,
  
  	.section_address = dwfl_offline_section_address,
  
  	/* We use this table for core files too.  */
  	.find_elf = dwfl_build_id_find_elf,
  };
469b9b884   Masami Hiramatsu   perf probe: Add b...
60
  /* Get a Dwarf from offline image */
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
61
  static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
ff7417835   Masami Hiramatsu   perf probe: Intro...
62
  					 const char *path)
469b9b884   Masami Hiramatsu   perf probe: Add b...
63
  {
ff7417835   Masami Hiramatsu   perf probe: Intro...
64
  	int fd;
469b9b884   Masami Hiramatsu   perf probe: Add b...
65

ff7417835   Masami Hiramatsu   perf probe: Intro...
66
67
68
  	fd = open(path, O_RDONLY);
  	if (fd < 0)
  		return fd;
469b9b884   Masami Hiramatsu   perf probe: Add b...
69

316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
70
71
  	dbg->dwfl = dwfl_begin(&offline_callbacks);
  	if (!dbg->dwfl)
ff7417835   Masami Hiramatsu   perf probe: Intro...
72
  		goto error;
469b9b884   Masami Hiramatsu   perf probe: Add b...
73

9135949dd   Masami Hiramatsu   perf probe: Begin...
74
  	dwfl_report_begin(dbg->dwfl);
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
75
76
  	dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
  	if (!dbg->mod)
469b9b884   Masami Hiramatsu   perf probe: Add b...
77
  		goto error;
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
78
79
  	dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
  	if (!dbg->dbg)
ff7417835   Masami Hiramatsu   perf probe: Intro...
80
  		goto error;
9135949dd   Masami Hiramatsu   perf probe: Begin...
81
  	dwfl_report_end(dbg->dwfl, NULL, NULL);
ff7417835   Masami Hiramatsu   perf probe: Intro...
82
  	return 0;
469b9b884   Masami Hiramatsu   perf probe: Add b...
83
  error:
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
84
85
  	if (dbg->dwfl)
  		dwfl_end(dbg->dwfl);
ff7417835   Masami Hiramatsu   perf probe: Intro...
86
87
  	else
  		close(fd);
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
88
  	memset(dbg, 0, sizeof(*dbg));
ff7417835   Masami Hiramatsu   perf probe: Intro...
89
90
  
  	return -ENOENT;
469b9b884   Masami Hiramatsu   perf probe: Add b...
91
  }
a15ad2f53   Masami Hiramatsu   perf probe: Suppo...
92
  static struct debuginfo *__debuginfo__new(const char *path)
ff7417835   Masami Hiramatsu   perf probe: Intro...
93
  {
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
94
95
  	struct debuginfo *dbg = zalloc(sizeof(*dbg));
  	if (!dbg)
3b4694de3   Masami Hiramatsu   perf probe: Fix t...
96
  		return NULL;
046625231   Arnaldo Carvalho de Melo   perf tools: Intro...
97
98
  	if (debuginfo__init_offline_dwarf(dbg, path) < 0)
  		zfree(&dbg);
a15ad2f53   Masami Hiramatsu   perf probe: Suppo...
99
100
101
  	if (dbg)
  		pr_debug("Open Debuginfo file: %s
  ", path);
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
102
  	return dbg;
ff7417835   Masami Hiramatsu   perf probe: Intro...
103
  }
a15ad2f53   Masami Hiramatsu   perf probe: Suppo...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
  enum dso_binary_type distro_dwarf_types[] = {
  	DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
  	DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
  	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
  	DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
  	DSO_BINARY_TYPE__NOT_FOUND,
  };
  
  struct debuginfo *debuginfo__new(const char *path)
  {
  	enum dso_binary_type *type;
  	char buf[PATH_MAX], nil = '\0';
  	struct dso *dso;
  	struct debuginfo *dinfo = NULL;
  
  	/* Try to open distro debuginfo files */
  	dso = dso__new(path);
  	if (!dso)
  		goto out;
  
  	for (type = distro_dwarf_types;
  	     !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND;
  	     type++) {
  		if (dso__read_binary_type_filename(dso, *type, &nil,
  						   buf, PATH_MAX) < 0)
  			continue;
  		dinfo = __debuginfo__new(buf);
  	}
d3a7c489c   Arnaldo Carvalho de Melo   perf tools: Refer...
132
  	dso__put(dso);
a15ad2f53   Masami Hiramatsu   perf probe: Suppo...
133
134
135
136
137
  
  out:
  	/* if failed to open all distro debuginfo, open given binary */
  	return dinfo ? : __debuginfo__new(path);
  }
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
138
  void debuginfo__delete(struct debuginfo *dbg)
ff7417835   Masami Hiramatsu   perf probe: Intro...
139
  {
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
140
141
142
143
  	if (dbg) {
  		if (dbg->dwfl)
  			dwfl_end(dbg->dwfl);
  		free(dbg);
ff7417835   Masami Hiramatsu   perf probe: Intro...
144
  	}
3b4694de3   Masami Hiramatsu   perf probe: Fix t...
145
  }
469b9b884   Masami Hiramatsu   perf probe: Add b...
146

4ea42b181   Masami Hiramatsu   perf: Add perf pr...
147
148
149
  /*
   * Probe finder related functions
   */
0e60836bb   Srikar Dronamraju   perf probe: Renam...
150
  static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
b7dcb857c   Masami Hiramatsu   perf probe: Suppo...
151
  {
0e60836bb   Srikar Dronamraju   perf probe: Renam...
152
153
  	struct probe_trace_arg_ref *ref;
  	ref = zalloc(sizeof(struct probe_trace_arg_ref));
b7dcb857c   Masami Hiramatsu   perf probe: Suppo...
154
155
156
157
  	if (ref != NULL)
  		ref->offset = offs;
  	return ref;
  }
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
158
159
160
  /*
   * Convert a location into trace_arg.
   * If tvar == NULL, this just checks variable can be converted.
3d918a12a   Masami Hiramatsu   perf probe: Find ...
161
162
   * If fentry == true and vr_die is a parameter, do huristic search
   * for the location fuzzed by function entry mcount.
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
163
164
   */
  static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
3d918a12a   Masami Hiramatsu   perf probe: Find ...
165
  				     Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
293d5b439   Masami Hiramatsu   perf probe: Suppo...
166
  				     unsigned int machine,
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
167
  				     struct probe_trace_arg *tvar)
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
168
  {
b7dcb857c   Masami Hiramatsu   perf probe: Suppo...
169
  	Dwarf_Attribute attr;
3d918a12a   Masami Hiramatsu   perf probe: Find ...
170
  	Dwarf_Addr tmp = 0;
b7dcb857c   Masami Hiramatsu   perf probe: Suppo...
171
172
  	Dwarf_Op *op;
  	size_t nops;
804b36068   Masami Hiramatsu   perf probe: Use e...
173
174
  	unsigned int regn;
  	Dwarf_Word offs = 0;
4235b0454   Masami Hiramatsu   perf probe: Intro...
175
  	bool ref = false;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
176
  	const char *regs;
349e8d261   He Kuang   perf probe: Add -...
177
  	int ret, ret2 = 0;
b7dcb857c   Masami Hiramatsu   perf probe: Suppo...
178

632941c4f   Masami Hiramatsu   perf probe: Suppo...
179
180
  	if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
  		goto static_var;
b7dcb857c   Masami Hiramatsu   perf probe: Suppo...
181
  	/* TODO: handle more than 1 exprs */
3d918a12a   Masami Hiramatsu   perf probe: Find ...
182
183
184
185
  	if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
  		return -EINVAL;	/* Broken DIE ? */
  	if (dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0) {
  		ret = dwarf_entrypc(sp_die, &tmp);
349e8d261   He Kuang   perf probe: Add -...
186
187
188
189
190
191
192
193
194
195
196
197
198
  		if (ret)
  			return -ENOENT;
  
  		if (probe_conf.show_location_range &&
  			(dwarf_tag(vr_die) == DW_TAG_variable)) {
  			ret2 = -ERANGE;
  		} else if (addr != tmp ||
  			dwarf_tag(vr_die) != DW_TAG_formal_parameter) {
  			return -ENOENT;
  		}
  
  		ret = dwarf_highpc(sp_die, &tmp);
  		if (ret)
3d918a12a   Masami Hiramatsu   perf probe: Find ...
199
200
201
202
203
204
205
206
207
208
  			return -ENOENT;
  		/*
  		 * This is fuzzed by fentry mcount. We try to find the
  		 * parameter location at the earliest address.
  		 */
  		for (addr += 1; addr <= tmp; addr++) {
  			if (dwarf_getlocation_addr(&attr, addr, &op,
  						   &nops, 1) > 0)
  				goto found;
  		}
b7dcb857c   Masami Hiramatsu   perf probe: Suppo...
209
210
  		return -ENOENT;
  	}
3d918a12a   Masami Hiramatsu   perf probe: Find ...
211
212
213
214
  found:
  	if (nops == 0)
  		/* TODO: Support const_value */
  		return -ENOENT;
b7dcb857c   Masami Hiramatsu   perf probe: Suppo...
215
216
  
  	if (op->atom == DW_OP_addr) {
632941c4f   Masami Hiramatsu   perf probe: Suppo...
217
  static_var:
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
218
  		if (!tvar)
349e8d261   He Kuang   perf probe: Add -...
219
  			return ret2;
b7dcb857c   Masami Hiramatsu   perf probe: Suppo...
220
221
222
223
224
225
226
227
228
  		/* Static variables on memory (not stack), make @varname */
  		ret = strlen(dwarf_diename(vr_die));
  		tvar->value = zalloc(ret + 2);
  		if (tvar->value == NULL)
  			return -ENOMEM;
  		snprintf(tvar->value, ret + 2, "@%s", dwarf_diename(vr_die));
  		tvar->ref = alloc_trace_arg_ref((long)offs);
  		if (tvar->ref == NULL)
  			return -ENOMEM;
349e8d261   He Kuang   perf probe: Add -...
229
  		return ret2;
b7dcb857c   Masami Hiramatsu   perf probe: Suppo...
230
  	}
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
231

4ea42b181   Masami Hiramatsu   perf: Add perf pr...
232
  	/* If this is based on frame buffer, set the offset */
804b36068   Masami Hiramatsu   perf probe: Use e...
233
  	if (op->atom == DW_OP_fbreg) {
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
234
  		if (fb_ops == NULL)
b55a87ade   Masami Hiramatsu   perf probe: Remov...
235
  			return -ENOTSUP;
4235b0454   Masami Hiramatsu   perf probe: Intro...
236
  		ref = true;
804b36068   Masami Hiramatsu   perf probe: Use e...
237
  		offs = op->number;
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
238
  		op = &fb_ops[0];
804b36068   Masami Hiramatsu   perf probe: Use e...
239
  	}
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
240

804b36068   Masami Hiramatsu   perf probe: Use e...
241
242
243
  	if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
  		regn = op->atom - DW_OP_breg0;
  		offs += op->number;
4235b0454   Masami Hiramatsu   perf probe: Intro...
244
  		ref = true;
804b36068   Masami Hiramatsu   perf probe: Use e...
245
246
247
248
249
  	} else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) {
  		regn = op->atom - DW_OP_reg0;
  	} else if (op->atom == DW_OP_bregx) {
  		regn = op->number;
  		offs += op->number2;
4235b0454   Masami Hiramatsu   perf probe: Intro...
250
  		ref = true;
804b36068   Masami Hiramatsu   perf probe: Use e...
251
252
  	} else if (op->atom == DW_OP_regx) {
  		regn = op->number;
b55a87ade   Masami Hiramatsu   perf probe: Remov...
253
  	} else {
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
254
255
  		pr_debug("DW_OP %x is not supported.
  ", op->atom);
b55a87ade   Masami Hiramatsu   perf probe: Remov...
256
257
  		return -ENOTSUP;
  	}
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
258

cf6eb489e   Masami Hiramatsu   perf probe: Show ...
259
  	if (!tvar)
349e8d261   He Kuang   perf probe: Add -...
260
  		return ret2;
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
261

293d5b439   Masami Hiramatsu   perf probe: Suppo...
262
  	regs = get_dwarf_regstr(regn, machine);
b55a87ade   Masami Hiramatsu   perf probe: Remov...
263
  	if (!regs) {
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
264
  		/* This should be a bug in DWARF or this tool */
0e43e5d22   Masami Hiramatsu   perf probe: Clean...
265
266
267
  		pr_warning("Mapping for the register number %u "
  			   "missing on this architecture.
  ", regn);
349e8d261   He Kuang   perf probe: Add -...
268
  		return -ENOTSUP;
b55a87ade   Masami Hiramatsu   perf probe: Remov...
269
  	}
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
270

02b95dadc   Masami Hiramatsu   perf probe: Remov...
271
272
273
  	tvar->value = strdup(regs);
  	if (tvar->value == NULL)
  		return -ENOMEM;
4235b0454   Masami Hiramatsu   perf probe: Intro...
274
  	if (ref) {
b7dcb857c   Masami Hiramatsu   perf probe: Suppo...
275
  		tvar->ref = alloc_trace_arg_ref((long)offs);
e334016f1   Masami Hiramatsu   perf probe: Remov...
276
277
  		if (tvar->ref == NULL)
  			return -ENOMEM;
4235b0454   Masami Hiramatsu   perf probe: Intro...
278
  	}
349e8d261   He Kuang   perf probe: Add -...
279
  	return ret2;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
280
  }
124bb83cd   Masami Hiramatsu   perf probe: Add b...
281
  #define BYTES_TO_BITS(nb)	((nb) * BITS_PER_LONG / sizeof(long))
b55a87ade   Masami Hiramatsu   perf probe: Remov...
282
  static int convert_variable_type(Dwarf_Die *vr_die,
0e60836bb   Srikar Dronamraju   perf probe: Renam...
283
  				 struct probe_trace_arg *tvar,
73317b954   Masami Hiramatsu   perf probe: Suppo...
284
  				 const char *cast)
4984912eb   Masami Hiramatsu   perf probe: Query...
285
  {
0e60836bb   Srikar Dronamraju   perf probe: Renam...
286
  	struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
4984912eb   Masami Hiramatsu   perf probe: Query...
287
288
  	Dwarf_Die type;
  	char buf[16];
5f03cba41   Masami Hiramatsu   perf probe: Make ...
289
  	char sbuf[STRERR_BUFSIZE];
bcfc08215   Masami Hiramatsu   perf probe: Remov...
290
  	int bsize, boffs, total;
4984912eb   Masami Hiramatsu   perf probe: Query...
291
  	int ret;
925437872   Masami Hiramatsu   perf probe: Suppo...
292
  	char prefix;
4984912eb   Masami Hiramatsu   perf probe: Query...
293

73317b954   Masami Hiramatsu   perf probe: Suppo...
294
  	/* TODO: check all types */
925437872   Masami Hiramatsu   perf probe: Suppo...
295
  	if (cast && strcmp(cast, "string") != 0 && strcmp(cast, "x") != 0 &&
19f00b011   Naohiro Aota   perf probe: Suppo...
296
  	    strcmp(cast, "s") != 0 && strcmp(cast, "u") != 0) {
73317b954   Masami Hiramatsu   perf probe: Suppo...
297
  		/* Non string type is OK */
925437872   Masami Hiramatsu   perf probe: Suppo...
298
  		/* and respect signedness/hexadecimal cast */
73317b954   Masami Hiramatsu   perf probe: Suppo...
299
300
301
  		tvar->type = strdup(cast);
  		return (tvar->type == NULL) ? -ENOMEM : 0;
  	}
bcfc08215   Masami Hiramatsu   perf probe: Remov...
302
303
  	bsize = dwarf_bitsize(vr_die);
  	if (bsize > 0) {
124bb83cd   Masami Hiramatsu   perf probe: Add b...
304
  		/* This is a bitfield */
bcfc08215   Masami Hiramatsu   perf probe: Remov...
305
306
307
308
309
310
  		boffs = dwarf_bitoffset(vr_die);
  		total = dwarf_bytesize(vr_die);
  		if (boffs < 0 || total < 0)
  			return -ENOENT;
  		ret = snprintf(buf, 16, "b%d@%d/%zd", bsize, boffs,
  				BYTES_TO_BITS(total));
124bb83cd   Masami Hiramatsu   perf probe: Add b...
311
312
  		goto formatted;
  	}
b55a87ade   Masami Hiramatsu   perf probe: Remov...
313
314
315
316
317
318
  	if (die_get_real_type(vr_die, &type) == NULL) {
  		pr_warning("Failed to get a type information of %s.
  ",
  			   dwarf_diename(vr_die));
  		return -ENOENT;
  	}
4984912eb   Masami Hiramatsu   perf probe: Query...
319

b2a3c12b7   Masami Hiramatsu   perf probe: Suppo...
320
321
322
  	pr_debug("%s type is %s.
  ",
  		 dwarf_diename(vr_die), dwarf_diename(&type));
73317b954   Masami Hiramatsu   perf probe: Suppo...
323
324
325
326
327
  	if (cast && strcmp(cast, "string") == 0) {	/* String type */
  		ret = dwarf_tag(&type);
  		if (ret != DW_TAG_pointer_type &&
  		    ret != DW_TAG_array_type) {
  			pr_warning("Failed to cast into string: "
0e43e5d22   Masami Hiramatsu   perf probe: Clean...
328
329
  				   "%s(%s) is not a pointer nor array.
  ",
73317b954   Masami Hiramatsu   perf probe: Suppo...
330
331
332
  				   dwarf_diename(vr_die), dwarf_diename(&type));
  			return -EINVAL;
  		}
7ce28b5b5   Hyeoncheol Lee   perf probe: Allow...
333
334
335
336
337
338
  		if (die_get_real_type(&type, &type) == NULL) {
  			pr_warning("Failed to get a type"
  				   " information.
  ");
  			return -ENOENT;
  		}
73317b954   Masami Hiramatsu   perf probe: Suppo...
339
  		if (ret == DW_TAG_pointer_type) {
73317b954   Masami Hiramatsu   perf probe: Suppo...
340
341
342
  			while (*ref_ptr)
  				ref_ptr = &(*ref_ptr)->next;
  			/* Add new reference with offset +0 */
0e60836bb   Srikar Dronamraju   perf probe: Renam...
343
  			*ref_ptr = zalloc(sizeof(struct probe_trace_arg_ref));
73317b954   Masami Hiramatsu   perf probe: Suppo...
344
345
346
347
348
349
  			if (*ref_ptr == NULL) {
  				pr_warning("Out of memory error
  ");
  				return -ENOMEM;
  			}
  		}
821756335   Masami Hiramatsu   perf probe: Fix t...
350
351
  		if (!die_compare_name(&type, "char") &&
  		    !die_compare_name(&type, "unsigned char")) {
73317b954   Masami Hiramatsu   perf probe: Suppo...
352
  			pr_warning("Failed to cast into string: "
0e43e5d22   Masami Hiramatsu   perf probe: Clean...
353
354
  				   "%s is not (unsigned) char *.
  ",
73317b954   Masami Hiramatsu   perf probe: Suppo...
355
356
357
358
359
360
  				   dwarf_diename(vr_die));
  			return -EINVAL;
  		}
  		tvar->type = strdup(cast);
  		return (tvar->type == NULL) ? -ENOMEM : 0;
  	}
19f00b011   Naohiro Aota   perf probe: Suppo...
361
  	if (cast && (strcmp(cast, "u") == 0))
925437872   Masami Hiramatsu   perf probe: Suppo...
362
  		prefix = 'u';
19f00b011   Naohiro Aota   perf probe: Suppo...
363
  	else if (cast && (strcmp(cast, "s") == 0))
925437872   Masami Hiramatsu   perf probe: Suppo...
364
365
366
367
  		prefix = 's';
  	else if (cast && (strcmp(cast, "x") == 0) &&
  		 probe_type_is_available(PROBE_TYPE_X))
  		prefix = 'x';
19f00b011   Naohiro Aota   perf probe: Suppo...
368
  	else
9880ce4a6   Masami Hiramatsu   perf probe: Use h...
369
370
  		prefix = die_is_signed_type(&type) ? 's' :
  			 probe_type_is_available(PROBE_TYPE_X) ? 'x' : 'u';
19f00b011   Naohiro Aota   perf probe: Suppo...
371

bcfc08215   Masami Hiramatsu   perf probe: Remov...
372
373
  	ret = dwarf_bytesize(&type);
  	if (ret <= 0)
124bb83cd   Masami Hiramatsu   perf probe: Add b...
374
375
  		/* No size ... try to use default type */
  		return 0;
bcfc08215   Masami Hiramatsu   perf probe: Remov...
376
  	ret = BYTES_TO_BITS(ret);
4984912eb   Masami Hiramatsu   perf probe: Query...
377

124bb83cd   Masami Hiramatsu   perf probe: Add b...
378
379
380
381
382
383
  	/* Check the bitwidth */
  	if (ret > MAX_BASIC_TYPE_BITS) {
  		pr_info("%s exceeds max-bitwidth. Cut down to %d bits.
  ",
  			dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
  		ret = MAX_BASIC_TYPE_BITS;
4984912eb   Masami Hiramatsu   perf probe: Query...
384
  	}
925437872   Masami Hiramatsu   perf probe: Suppo...
385
  	ret = snprintf(buf, 16, "%c%d", prefix, ret);
124bb83cd   Masami Hiramatsu   perf probe: Add b...
386
387
388
389
390
391
392
  
  formatted:
  	if (ret < 0 || ret >= 16) {
  		if (ret >= 16)
  			ret = -E2BIG;
  		pr_warning("Failed to convert variable type: %s
  ",
c8b5f2c96   Arnaldo Carvalho de Melo   tools: Introduce ...
393
  			   str_error_r(-ret, sbuf, sizeof(sbuf)));
124bb83cd   Masami Hiramatsu   perf probe: Add b...
394
395
396
397
398
  		return ret;
  	}
  	tvar->type = strdup(buf);
  	if (tvar->type == NULL)
  		return -ENOMEM;
b55a87ade   Masami Hiramatsu   perf probe: Remov...
399
  	return 0;
4984912eb   Masami Hiramatsu   perf probe: Query...
400
  }
b55a87ade   Masami Hiramatsu   perf probe: Remov...
401
  static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
7df2f3295   Masami Hiramatsu   perf probe: Add d...
402
  				    struct perf_probe_arg_field *field,
0e60836bb   Srikar Dronamraju   perf probe: Renam...
403
  				    struct probe_trace_arg_ref **ref_ptr,
4984912eb   Masami Hiramatsu   perf probe: Query...
404
  				    Dwarf_Die *die_mem)
7df2f3295   Masami Hiramatsu   perf probe: Add d...
405
  {
0e60836bb   Srikar Dronamraju   perf probe: Renam...
406
  	struct probe_trace_arg_ref *ref = *ref_ptr;
7df2f3295   Masami Hiramatsu   perf probe: Add d...
407
408
  	Dwarf_Die type;
  	Dwarf_Word offs;
b2a3c12b7   Masami Hiramatsu   perf probe: Suppo...
409
  	int ret, tag;
7df2f3295   Masami Hiramatsu   perf probe: Add d...
410
411
412
  
  	pr_debug("converting %s in %s
  ", field->name, varname);
b55a87ade   Masami Hiramatsu   perf probe: Remov...
413
414
415
416
417
  	if (die_get_real_type(vr_die, &type) == NULL) {
  		pr_warning("Failed to get the type of %s.
  ", varname);
  		return -ENOENT;
  	}
b2a3c12b7   Masami Hiramatsu   perf probe: Suppo...
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
  	pr_debug2("Var real type: (%x)
  ", (unsigned)dwarf_dieoffset(&type));
  	tag = dwarf_tag(&type);
  
  	if (field->name[0] == '[' &&
  	    (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) {
  		if (field->next)
  			/* Save original type for next field */
  			memcpy(die_mem, &type, sizeof(*die_mem));
  		/* Get the type of this array */
  		if (die_get_real_type(&type, &type) == NULL) {
  			pr_warning("Failed to get the type of %s.
  ", varname);
  			return -ENOENT;
  		}
  		pr_debug2("Array real type: (%x)
  ",
  			 (unsigned)dwarf_dieoffset(&type));
  		if (tag == DW_TAG_pointer_type) {
0e60836bb   Srikar Dronamraju   perf probe: Renam...
437
  			ref = zalloc(sizeof(struct probe_trace_arg_ref));
b2a3c12b7   Masami Hiramatsu   perf probe: Suppo...
438
439
440
441
442
443
444
  			if (ref == NULL)
  				return -ENOMEM;
  			if (*ref_ptr)
  				(*ref_ptr)->next = ref;
  			else
  				*ref_ptr = ref;
  		}
bcfc08215   Masami Hiramatsu   perf probe: Remov...
445
  		ref->offset += dwarf_bytesize(&type) * field->index;
b2a3c12b7   Masami Hiramatsu   perf probe: Suppo...
446
447
448
449
450
451
  		if (!field->next)
  			/* Save vr_die for converting types */
  			memcpy(die_mem, vr_die, sizeof(*die_mem));
  		goto next;
  	} else if (tag == DW_TAG_pointer_type) {
  		/* Check the pointer and dereference */
b55a87ade   Masami Hiramatsu   perf probe: Remov...
452
453
454
455
456
457
  		if (!field->ref) {
  			pr_err("Semantic error: %s must be referred by '->'
  ",
  			       field->name);
  			return -EINVAL;
  		}
7df2f3295   Masami Hiramatsu   perf probe: Add d...
458
  		/* Get the type pointed by this pointer */
b55a87ade   Masami Hiramatsu   perf probe: Remov...
459
460
461
462
463
  		if (die_get_real_type(&type, &type) == NULL) {
  			pr_warning("Failed to get the type of %s.
  ", varname);
  			return -ENOENT;
  		}
12e5a7ae4   Masami Hiramatsu   perf probe: Corre...
464
  		/* Verify it is a data structure  */
7b0295b3d   Hyeoncheol Lee   perf probe: Add u...
465
466
  		tag = dwarf_tag(&type);
  		if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
03440c4e5   Masahiro Yamada   scripts/spelling....
467
468
  			pr_warning("%s is not a data structure nor a union.
  ",
7b0295b3d   Hyeoncheol Lee   perf probe: Add u...
469
  				   varname);
b55a87ade   Masami Hiramatsu   perf probe: Remov...
470
471
  			return -EINVAL;
  		}
12e5a7ae4   Masami Hiramatsu   perf probe: Corre...
472

0e60836bb   Srikar Dronamraju   perf probe: Renam...
473
  		ref = zalloc(sizeof(struct probe_trace_arg_ref));
e334016f1   Masami Hiramatsu   perf probe: Remov...
474
475
  		if (ref == NULL)
  			return -ENOMEM;
7df2f3295   Masami Hiramatsu   perf probe: Add d...
476
477
478
479
480
  		if (*ref_ptr)
  			(*ref_ptr)->next = ref;
  		else
  			*ref_ptr = ref;
  	} else {
12e5a7ae4   Masami Hiramatsu   perf probe: Corre...
481
  		/* Verify it is a data structure  */
7b0295b3d   Hyeoncheol Lee   perf probe: Add u...
482
  		if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
03440c4e5   Masahiro Yamada   scripts/spelling....
483
484
  			pr_warning("%s is not a data structure nor a union.
  ",
7b0295b3d   Hyeoncheol Lee   perf probe: Add u...
485
  				   varname);
b55a87ade   Masami Hiramatsu   perf probe: Remov...
486
487
  			return -EINVAL;
  		}
b2a3c12b7   Masami Hiramatsu   perf probe: Suppo...
488
  		if (field->name[0] == '[') {
d939be3ad   Masanari Iida   treewide: Fix typ...
489
  			pr_err("Semantic error: %s is not a pointer"
0e43e5d22   Masami Hiramatsu   perf probe: Clean...
490
491
  			       " nor array.
  ", varname);
b2a3c12b7   Masami Hiramatsu   perf probe: Suppo...
492
493
  			return -EINVAL;
  		}
c72738355   Masami Hiramatsu   perf probe: Fix t...
494
495
  		/* While prcessing unnamed field, we don't care about this */
  		if (field->ref && dwarf_diename(vr_die)) {
b55a87ade   Masami Hiramatsu   perf probe: Remov...
496
497
498
499
500
501
502
503
504
505
506
  			pr_err("Semantic error: %s must be referred by '.'
  ",
  			       field->name);
  			return -EINVAL;
  		}
  		if (!ref) {
  			pr_warning("Structure on a register is not "
  				   "supported yet.
  ");
  			return -ENOTSUP;
  		}
7df2f3295   Masami Hiramatsu   perf probe: Add d...
507
  	}
b55a87ade   Masami Hiramatsu   perf probe: Remov...
508
  	if (die_find_member(&type, field->name, die_mem) == NULL) {
9ef0438a9   Arnaldo Carvalho de Melo   perf probe: Fix typo
509
510
  		pr_warning("%s(type:%s) has no member %s.
  ", varname,
b55a87ade   Masami Hiramatsu   perf probe: Remov...
511
512
513
  			   dwarf_diename(&type), field->name);
  		return -EINVAL;
  	}
7df2f3295   Masami Hiramatsu   perf probe: Add d...
514
515
  
  	/* Get the offset of the field */
7b0295b3d   Hyeoncheol Lee   perf probe: Add u...
516
517
518
519
520
521
522
523
524
525
  	if (tag == DW_TAG_union_type) {
  		offs = 0;
  	} else {
  		ret = die_get_data_member_location(die_mem, &offs);
  		if (ret < 0) {
  			pr_warning("Failed to get the offset of %s.
  ",
  				   field->name);
  			return ret;
  		}
b55a87ade   Masami Hiramatsu   perf probe: Remov...
526
  	}
7df2f3295   Masami Hiramatsu   perf probe: Add d...
527
  	ref->offset += (long)offs;
c72738355   Masami Hiramatsu   perf probe: Fix t...
528
529
530
531
  	/* If this member is unnamed, we need to reuse this field */
  	if (!dwarf_diename(die_mem))
  		return convert_variable_fields(die_mem, varname, field,
  						&ref, die_mem);
b2a3c12b7   Masami Hiramatsu   perf probe: Suppo...
532
  next:
7df2f3295   Masami Hiramatsu   perf probe: Add d...
533
534
  	/* Converting next field */
  	if (field->next)
b55a87ade   Masami Hiramatsu   perf probe: Remov...
535
  		return convert_variable_fields(die_mem, field->name,
de1439d8a   Masami Hiramatsu   perf probe: Suppo...
536
  					field->next, &ref, die_mem);
b55a87ade   Masami Hiramatsu   perf probe: Remov...
537
538
  	else
  		return 0;
7df2f3295   Masami Hiramatsu   perf probe: Add d...
539
  }
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
540
  /* Show a variables in kprobe event format */
b55a87ade   Masami Hiramatsu   perf probe: Remov...
541
  static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
542
  {
4984912eb   Masami Hiramatsu   perf probe: Query...
543
  	Dwarf_Die die_mem;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
544
  	int ret;
b7dcb857c   Masami Hiramatsu   perf probe: Suppo...
545
546
547
  	pr_debug("Converting variable %s into trace event.
  ",
  		 dwarf_diename(vr_die));
804b36068   Masami Hiramatsu   perf probe: Use e...
548

cf6eb489e   Masami Hiramatsu   perf probe: Show ...
549
  	ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
293d5b439   Masami Hiramatsu   perf probe: Suppo...
550
  					&pf->sp_die, pf->machine, pf->tvar);
7d5eaba9b   He Kuang   perf probe: Show ...
551
552
553
554
555
556
557
558
559
  	if (ret == -ENOENT || ret == -EINVAL) {
  		pr_err("Failed to find the location of the '%s' variable at this address.
  "
  		       " Perhaps it has been optimized out.
  "
  		       " Use -V with the --range option to show '%s' location range.
  ",
  		       pf->pvar->var, pf->pvar->var);
  	} else if (ret == -ENOTSUP)
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
560
561
  		pr_err("Sorry, we don't support this variable location yet.
  ");
0c188a07b   Masami Hiramatsu   perf probe: Fix a...
562
  	else if (ret == 0 && pf->pvar->field) {
b55a87ade   Masami Hiramatsu   perf probe: Remov...
563
564
565
  		ret = convert_variable_fields(vr_die, pf->pvar->var,
  					      pf->pvar->field, &pf->tvar->ref,
  					      &die_mem);
4984912eb   Masami Hiramatsu   perf probe: Query...
566
567
  		vr_die = &die_mem;
  	}
73317b954   Masami Hiramatsu   perf probe: Suppo...
568
569
  	if (ret == 0)
  		ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
804b36068   Masami Hiramatsu   perf probe: Use e...
570
  	/* *expr will be cached in libdw. Don't free it. */
b55a87ade   Masami Hiramatsu   perf probe: Remov...
571
  	return ret;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
572
  }
221d06118   Masami Hiramatsu   perf probe: Fix t...
573
574
  /* Find a variable in a scope DIE */
  static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
575
  {
f182e3e13   Masami Hiramatsu   perf probe: Avoid...
576
  	Dwarf_Die vr_die;
909b0360a   Masami Hiramatsu   perf probe: Use s...
577
  	char *buf, *ptr;
f182e3e13   Masami Hiramatsu   perf probe: Avoid...
578
  	int ret = 0;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
579

da15bd9df   Wang Nan   perf probe: Suppo...
580
581
582
  	/* Copy raw parameters */
  	if (!is_c_varname(pf->pvar->var))
  		return copy_to_probe_trace_arg(pf->tvar, pf->pvar);
367e94c10   Masami Hiramatsu   perf probe: Fix h...
583

48481938b   Masami Hiramatsu   perf probe: Suppo...
584
  	if (pf->pvar->name)
02b95dadc   Masami Hiramatsu   perf probe: Remov...
585
  		pf->tvar->name = strdup(pf->pvar->name);
48481938b   Masami Hiramatsu   perf probe: Suppo...
586
  	else {
909b0360a   Masami Hiramatsu   perf probe: Use s...
587
588
589
  		buf = synthesize_perf_probe_arg(pf->pvar);
  		if (!buf)
  			return -ENOMEM;
11a1ca355   Masami Hiramatsu   perf probe: Suppo...
590
591
592
  		ptr = strchr(buf, ':');	/* Change type separator to _ */
  		if (ptr)
  			*ptr = '_';
909b0360a   Masami Hiramatsu   perf probe: Use s...
593
  		pf->tvar->name = buf;
48481938b   Masami Hiramatsu   perf probe: Suppo...
594
  	}
02b95dadc   Masami Hiramatsu   perf probe: Remov...
595
596
  	if (pf->tvar->name == NULL)
  		return -ENOMEM;
48481938b   Masami Hiramatsu   perf probe: Suppo...
597

f182e3e13   Masami Hiramatsu   perf probe: Avoid...
598
599
  	pr_debug("Searching '%s' variable in context.
  ", pf->pvar->var);
b55a87ade   Masami Hiramatsu   perf probe: Remov...
600
  	/* Search child die for local variables and parameters. */
f182e3e13   Masami Hiramatsu   perf probe: Avoid...
601
602
  	if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) {
  		/* Search again in global variables */
d13855ef1   He Kuang   perf probe: Fix b...
603
604
  		if (!die_find_variable_at(&pf->cu_die, pf->pvar->var,
  						0, &vr_die)) {
36d789a4d   Masami Hiramatsu   perf probe: Impro...
605
606
607
  			pr_warning("Failed to find '%s' in this function.
  ",
  				   pf->pvar->var);
f182e3e13   Masami Hiramatsu   perf probe: Avoid...
608
  			ret = -ENOENT;
d13855ef1   He Kuang   perf probe: Fix b...
609
  		}
b7dcb857c   Masami Hiramatsu   perf probe: Suppo...
610
  	}
f66fedcb7   Masami Hiramatsu   perf probe: Fix r...
611
  	if (ret >= 0)
f182e3e13   Masami Hiramatsu   perf probe: Avoid...
612
  		ret = convert_variable(&vr_die, pf);
b7dcb857c   Masami Hiramatsu   perf probe: Suppo...
613
  	return ret;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
614
  }
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
615
  /* Convert subprogram DIE to trace point */
576b52372   Masami Hiramatsu   perf probe: Fix p...
616
617
  static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
  				  Dwarf_Addr paddr, bool retprobe,
6cca13bdf   Masami Hiramatsu   perf probe: Impro...
618
  				  const char *function,
576b52372   Masami Hiramatsu   perf probe: Fix p...
619
  				  struct probe_trace_point *tp)
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
620
  {
26b795249   Prashanth Nageshappa   perf probe: Ensur...
621
  	Dwarf_Addr eaddr, highaddr;
576b52372   Masami Hiramatsu   perf probe: Fix p...
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
  	GElf_Sym sym;
  	const char *symbol;
  
  	/* Verify the address is correct */
  	if (dwarf_entrypc(sp_die, &eaddr) != 0) {
  		pr_warning("Failed to get entry address of %s
  ",
  			   dwarf_diename(sp_die));
  		return -ENOENT;
  	}
  	if (dwarf_highpc(sp_die, &highaddr) != 0) {
  		pr_warning("Failed to get end address of %s
  ",
  			   dwarf_diename(sp_die));
  		return -ENOENT;
  	}
  	if (paddr > highaddr) {
  		pr_warning("Offset specified is greater than size of %s
  ",
  			   dwarf_diename(sp_die));
  		return -EINVAL;
  	}
664fee3dc   Masami Hiramatsu   perf probe: Do no...
644
  	symbol = dwarf_diename(sp_die);
576b52372   Masami Hiramatsu   perf probe: Fix p...
645
  	if (!symbol) {
664fee3dc   Masami Hiramatsu   perf probe: Do no...
646
647
648
649
650
651
652
653
654
  		/* Try to get the symbol name from symtab */
  		symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
  		if (!symbol) {
  			pr_warning("Failed to find symbol at 0x%lx
  ",
  				   (unsigned long)paddr);
  			return -ENOENT;
  		}
  		eaddr = sym.st_value;
576b52372   Masami Hiramatsu   perf probe: Fix p...
655
  	}
664fee3dc   Masami Hiramatsu   perf probe: Do no...
656
  	tp->offset = (unsigned long)(paddr - eaddr);
fb7345bbf   Masami Hiramatsu   perf probe: Suppo...
657
  	tp->address = (unsigned long)paddr;
576b52372   Masami Hiramatsu   perf probe: Fix p...
658
659
660
  	tp->symbol = strdup(symbol);
  	if (!tp->symbol)
  		return -ENOMEM;
4235b0454   Masami Hiramatsu   perf probe: Intro...
661

04ddd04b0   Masami Hiramatsu   perf probe: Fix r...
662
  	/* Return probe must be on the head of a subprogram */
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
663
664
  	if (retprobe) {
  		if (eaddr != paddr) {
6cca13bdf   Masami Hiramatsu   perf probe: Impro...
665
666
667
668
669
670
  			pr_warning("Failed to find \"%s%%return\",
  "
  				   " because %s is an inlined function and"
  				   " has no return point.
  ", function,
  				   function);
04ddd04b0   Masami Hiramatsu   perf probe: Fix r...
671
672
  			return -EINVAL;
  		}
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
673
  		tp->retprobe = true;
04ddd04b0   Masami Hiramatsu   perf probe: Fix r...
674
  	}
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
675
676
  	return 0;
  }
221d06118   Masami Hiramatsu   perf probe: Fix t...
677
678
  /* Call probe_finder callback with scope DIE */
  static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
679
  {
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
680
  	Dwarf_Attribute fb_attr;
4d3b16269   Masami Hiramatsu   perf probe: Fix t...
681
  	Dwarf_Frame *frame = NULL;
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
682
683
  	size_t nops;
  	int ret;
221d06118   Masami Hiramatsu   perf probe: Fix t...
684
685
686
687
688
689
690
  	if (!sc_die) {
  		pr_err("Caller must pass a scope DIE. Program error.
  ");
  		return -EINVAL;
  	}
  
  	/* If not a real subprogram, find a real one */
0dbb1cac1   Masami Hiramatsu   perf probe: Fix f...
691
  	if (!die_is_func_def(sc_die)) {
221d06118   Masami Hiramatsu   perf probe: Fix t...
692
  		if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
d4c537e6b   Naveen N. Rao   perf probe: Ignor...
693
694
695
696
697
698
699
700
701
702
703
  			if (die_find_tailfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
  				pr_warning("Ignoring tail call from %s
  ",
  						dwarf_diename(&pf->sp_die));
  				return 0;
  			} else {
  				pr_warning("Failed to find probe point in any "
  					   "functions.
  ");
  				return -ENOENT;
  			}
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
704
  		}
221d06118   Masami Hiramatsu   perf probe: Fix t...
705
706
  	} else
  		memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die));
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
707

221d06118   Masami Hiramatsu   perf probe: Fix t...
708
709
  	/* Get the frame base attribute/ops from subprogram */
  	dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr);
d0cb4260f   Masami Hiramatsu   perf probe: Use o...
710
  	ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
a34a98549   Masami Hiramatsu   perf probe: Suppo...
711
  	if (ret <= 0 || nops == 0) {
804b36068   Masami Hiramatsu   perf probe: Use e...
712
  		pf->fb_ops = NULL;
7752f1b09   Masami Hiramatsu   perf probe: Don't...
713
  #if _ELFUTILS_PREREQ(0, 142)
a34a98549   Masami Hiramatsu   perf probe: Suppo...
714
  	} else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
270bde1e7   Hemant Kumar   perf probe: Searc...
715
716
717
  		   (pf->cfi_eh != NULL || pf->cfi_dbg != NULL)) {
  		if ((dwarf_cfi_addrframe(pf->cfi_eh, pf->addr, &frame) != 0 &&
  		     (dwarf_cfi_addrframe(pf->cfi_dbg, pf->addr, &frame) != 0)) ||
b55a87ade   Masami Hiramatsu   perf probe: Remov...
718
  		    dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
0e43e5d22   Masami Hiramatsu   perf probe: Clean...
719
720
  			pr_warning("Failed to get call frame on 0x%jx
  ",
b55a87ade   Masami Hiramatsu   perf probe: Remov...
721
  				   (uintmax_t)pf->addr);
4d3b16269   Masami Hiramatsu   perf probe: Fix t...
722
723
  			free(frame);
  			return -ENOENT;
b55a87ade   Masami Hiramatsu   perf probe: Remov...
724
  		}
7752f1b09   Masami Hiramatsu   perf probe: Don't...
725
  #endif
a34a98549   Masami Hiramatsu   perf probe: Suppo...
726
  	}
804b36068   Masami Hiramatsu   perf probe: Use e...
727

cf6eb489e   Masami Hiramatsu   perf probe: Show ...
728
  	/* Call finder's callback handler */
4d3b16269   Masami Hiramatsu   perf probe: Fix t...
729
  	ret = pf->callback(sc_die, pf);
804b36068   Masami Hiramatsu   perf probe: Use e...
730

4d3b16269   Masami Hiramatsu   perf probe: Fix t...
731
732
  	/* Since *pf->fb_ops can be a part of frame. we should free it here. */
  	free(frame);
804b36068   Masami Hiramatsu   perf probe: Use e...
733
  	pf->fb_ops = NULL;
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
734
735
  
  	return ret;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
736
  }
221d06118   Masami Hiramatsu   perf probe: Fix t...
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
  struct find_scope_param {
  	const char *function;
  	const char *file;
  	int line;
  	int diff;
  	Dwarf_Die *die_mem;
  	bool found;
  };
  
  static int find_best_scope_cb(Dwarf_Die *fn_die, void *data)
  {
  	struct find_scope_param *fsp = data;
  	const char *file;
  	int lno;
  
  	/* Skip if declared file name does not match */
  	if (fsp->file) {
  		file = dwarf_decl_file(fn_die);
  		if (!file || strcmp(fsp->file, file) != 0)
  			return 0;
  	}
  	/* If the function name is given, that's what user expects */
  	if (fsp->function) {
4c8593512   Masami Hiramatsu   perf probe: Suppo...
760
  		if (die_match_name(fn_die, fsp->function)) {
221d06118   Masami Hiramatsu   perf probe: Fix t...
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
  			memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
  			fsp->found = true;
  			return 1;
  		}
  	} else {
  		/* With the line number, find the nearest declared DIE */
  		dwarf_decl_line(fn_die, &lno);
  		if (lno < fsp->line && fsp->diff > fsp->line - lno) {
  			/* Keep a candidate and continue */
  			fsp->diff = fsp->line - lno;
  			memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
  			fsp->found = true;
  		}
  	}
  	return 0;
  }
  
  /* Find an appropriate scope fits to given conditions */
  static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem)
  {
  	struct find_scope_param fsp = {
  		.function = pf->pev->point.function,
  		.file = pf->fname,
  		.line = pf->lno,
  		.diff = INT_MAX,
  		.die_mem = die_mem,
  		.found = false,
  	};
  
  	cu_walk_functions_at(&pf->cu_die, pf->addr, find_best_scope_cb, &fsp);
  
  	return fsp.found ? die_mem : NULL;
  }
4cc9cec63   Masami Hiramatsu   perf probe: Intro...
794
795
  static int probe_point_line_walker(const char *fname, int lineno,
  				   Dwarf_Addr addr, void *data)
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
796
  {
4cc9cec63   Masami Hiramatsu   perf probe: Intro...
797
  	struct probe_finder *pf = data;
221d06118   Masami Hiramatsu   perf probe: Fix t...
798
  	Dwarf_Die *sc_die, die_mem;
4cc9cec63   Masami Hiramatsu   perf probe: Intro...
799
  	int ret;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
800

4cc9cec63   Masami Hiramatsu   perf probe: Intro...
801
802
  	if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0)
  		return 0;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
803

4cc9cec63   Masami Hiramatsu   perf probe: Intro...
804
  	pf->addr = addr;
221d06118   Masami Hiramatsu   perf probe: Fix t...
805
806
807
808
809
810
811
812
  	sc_die = find_best_scope(pf, &die_mem);
  	if (!sc_die) {
  		pr_warning("Failed to find scope of probe point.
  ");
  		return -ENOENT;
  	}
  
  	ret = call_probe_finder(sc_die, pf);
b0ef07324   Masami Hiramatsu   perf/probes: Supp...
813

4cc9cec63   Masami Hiramatsu   perf probe: Intro...
814
  	/* Continue if no error, because the line will be in inline function */
fbee632d0   Arnaldo Carvalho de Melo   perf probe: Fix e...
815
  	return ret < 0 ? ret : 0;
4cc9cec63   Masami Hiramatsu   perf probe: Intro...
816
  }
804b36068   Masami Hiramatsu   perf probe: Use e...
817

4cc9cec63   Masami Hiramatsu   perf probe: Intro...
818
819
820
821
  /* Find probe point from its line number */
  static int find_probe_point_by_line(struct probe_finder *pf)
  {
  	return die_walk_lines(&pf->cu_die, probe_point_line_walker, pf);
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
822
  }
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
823
  /* Find lines which match lazy pattern */
5a62257a3   Masami Hiramatsu   perf probe: Repla...
824
  static int find_lazy_match_lines(struct intlist *list,
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
825
826
  				 const char *fname, const char *pat)
  {
f50c2169b   Franck Bui-Huu   perf probe: Rewri...
827
828
829
830
831
  	FILE *fp;
  	char *line = NULL;
  	size_t line_len;
  	ssize_t len;
  	int count = 0, linenum = 1;
5f03cba41   Masami Hiramatsu   perf probe: Make ...
832
  	char sbuf[STRERR_BUFSIZE];
f50c2169b   Franck Bui-Huu   perf probe: Rewri...
833
834
835
  
  	fp = fopen(fname, "r");
  	if (!fp) {
5f03cba41   Masami Hiramatsu   perf probe: Make ...
836
837
  		pr_warning("Failed to open %s: %s
  ", fname,
c8b5f2c96   Arnaldo Carvalho de Melo   tools: Introduce ...
838
  			   str_error_r(errno, sbuf, sizeof(sbuf)));
b448c4b61   Arnaldo Carvalho de Melo   perf probe: Fix s...
839
  		return -errno;
b55a87ade   Masami Hiramatsu   perf probe: Remov...
840
  	}
f50c2169b   Franck Bui-Huu   perf probe: Rewri...
841
  	while ((len = getline(&line, &line_len, fp)) > 0) {
b448c4b61   Arnaldo Carvalho de Melo   perf probe: Fix s...
842

f50c2169b   Franck Bui-Huu   perf probe: Rewri...
843
844
845
846
847
  		if (line[len - 1] == '
  ')
  			line[len - 1] = '\0';
  
  		if (strlazymatch(line, pat)) {
5a62257a3   Masami Hiramatsu   perf probe: Repla...
848
  			intlist__add(list, linenum);
f50c2169b   Franck Bui-Huu   perf probe: Rewri...
849
  			count++;
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
850
  		}
f50c2169b   Franck Bui-Huu   perf probe: Rewri...
851
  		linenum++;
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
852
  	}
f50c2169b   Franck Bui-Huu   perf probe: Rewri...
853
854
855
856
857
858
859
860
861
862
  
  	if (ferror(fp))
  		count = -errno;
  	free(line);
  	fclose(fp);
  
  	if (count == 0)
  		pr_debug("No matched lines found in %s.
  ", fname);
  	return count;
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
863
  }
4cc9cec63   Masami Hiramatsu   perf probe: Intro...
864
865
866
867
  static int probe_point_lazy_walker(const char *fname, int lineno,
  				   Dwarf_Addr addr, void *data)
  {
  	struct probe_finder *pf = data;
221d06118   Masami Hiramatsu   perf probe: Fix t...
868
  	Dwarf_Die *sc_die, die_mem;
4cc9cec63   Masami Hiramatsu   perf probe: Intro...
869
  	int ret;
5a62257a3   Masami Hiramatsu   perf probe: Repla...
870
  	if (!intlist__has_entry(pf->lcache, lineno) ||
4cc9cec63   Masami Hiramatsu   perf probe: Intro...
871
872
873
874
875
876
877
  	    strtailcmp(fname, pf->fname) != 0)
  		return 0;
  
  	pr_debug("Probe line found: line:%d addr:0x%llx
  ",
  		 lineno, (unsigned long long)addr);
  	pf->addr = addr;
221d06118   Masami Hiramatsu   perf probe: Fix t...
878
879
880
881
882
883
884
885
886
  	pf->lno = lineno;
  	sc_die = find_best_scope(pf, &die_mem);
  	if (!sc_die) {
  		pr_warning("Failed to find scope of probe point.
  ");
  		return -ENOENT;
  	}
  
  	ret = call_probe_finder(sc_die, pf);
4cc9cec63   Masami Hiramatsu   perf probe: Intro...
887
888
889
890
891
  
  	/*
  	 * Continue if no error, because the lazy pattern will match
  	 * to other lines
  	 */
5e814dd59   Ingo Molnar   perf probe: Clean...
892
  	return ret < 0 ? ret : 0;
4cc9cec63   Masami Hiramatsu   perf probe: Intro...
893
  }
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
894
  /* Find probe points from lazy pattern  */
b55a87ade   Masami Hiramatsu   perf probe: Remov...
895
  static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
896
  {
b55a87ade   Masami Hiramatsu   perf probe: Remov...
897
  	int ret = 0;
09ed8975c   Naohiro Aota   perf probe: Find ...
898
  	char *fpath;
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
899

5a62257a3   Masami Hiramatsu   perf probe: Repla...
900
  	if (intlist__empty(pf->lcache)) {
09ed8975c   Naohiro Aota   perf probe: Find ...
901
902
903
904
905
906
907
908
909
  		const char *comp_dir;
  
  		comp_dir = cu_get_comp_dir(&pf->cu_die);
  		ret = get_real_path(pf->fname, comp_dir, &fpath);
  		if (ret < 0) {
  			pr_warning("Failed to find source file path.
  ");
  			return ret;
  		}
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
910
  		/* Matching lazy line pattern */
09ed8975c   Naohiro Aota   perf probe: Find ...
911
  		ret = find_lazy_match_lines(pf->lcache, fpath,
4235b0454   Masami Hiramatsu   perf probe: Intro...
912
  					    pf->pev->point.lazy_line);
09ed8975c   Naohiro Aota   perf probe: Find ...
913
  		free(fpath);
f50c2169b   Franck Bui-Huu   perf probe: Rewri...
914
  		if (ret <= 0)
b55a87ade   Masami Hiramatsu   perf probe: Remov...
915
  			return ret;
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
916
  	}
4cc9cec63   Masami Hiramatsu   perf probe: Intro...
917
  	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
918
  }
e47392bf9   Ravi Bangoria   perf uprobe: Skip...
919
920
921
922
923
924
925
926
927
  static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
  {
  	struct perf_probe_point *pp = &pf->pev->point;
  
  	/* Not uprobe? */
  	if (!pf->pev->uprobes)
  		return;
  
  	/* Compiled with optimization? */
6243b9dc4   Ravi Bangoria   perf probe: Move ...
928
  	if (die_is_optimized_target(&pf->cu_die))
e47392bf9   Ravi Bangoria   perf uprobe: Skip...
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
  		return;
  
  	/* Don't know entrypc? */
  	if (!pf->addr)
  		return;
  
  	/* Only FUNC and FUNC@SRC are eligible. */
  	if (!pp->function || pp->line || pp->retprobe || pp->lazy_line ||
  	    pp->offset || pp->abs_address)
  		return;
  
  	/* Not interested in func parameter? */
  	if (!perf_probe_with_var(pf->pev))
  		return;
  
  	pr_info("Target program is compiled without optimization. Skipping prologue.
  "
  		"Probe on address 0x%" PRIx64 " to force probing at the function entry.
  
  ",
  		pf->addr);
6243b9dc4   Ravi Bangoria   perf probe: Move ...
950
  	die_skip_prologue(sp_die, &pf->cu_die, &pf->addr);
e47392bf9   Ravi Bangoria   perf uprobe: Skip...
951
  }
e92b85e1f   Masami Hiramatsu   perf probe: Use l...
952
953
  static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
  {
db0d2c642   Masami Hiramatsu   perf probe: Searc...
954
  	struct probe_finder *pf = data;
4235b0454   Masami Hiramatsu   perf probe: Intro...
955
  	struct perf_probe_point *pp = &pf->pev->point;
b55a87ade   Masami Hiramatsu   perf probe: Remov...
956
  	Dwarf_Addr addr;
db0d2c642   Masami Hiramatsu   perf probe: Searc...
957
  	int ret;
e92b85e1f   Masami Hiramatsu   perf probe: Use l...
958

2a9c8c360   Masami Hiramatsu   perf probe: Add l...
959
  	if (pp->lazy_line)
db0d2c642   Masami Hiramatsu   perf probe: Searc...
960
  		ret = find_probe_point_lazy(in_die, pf);
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
961
962
  	else {
  		/* Get probe address */
b55a87ade   Masami Hiramatsu   perf probe: Remov...
963
  		if (dwarf_entrypc(in_die, &addr) != 0) {
0e43e5d22   Masami Hiramatsu   perf probe: Clean...
964
965
  			pr_warning("Failed to get entry address of %s.
  ",
b55a87ade   Masami Hiramatsu   perf probe: Remov...
966
  				   dwarf_diename(in_die));
db0d2c642   Masami Hiramatsu   perf probe: Searc...
967
  			return -ENOENT;
b55a87ade   Masami Hiramatsu   perf probe: Remov...
968
  		}
0ad45b33c   Masami Hiramatsu   perf probe: Skip ...
969
970
971
972
973
974
  		if (addr == 0) {
  			pr_debug("%s has no valid entry address. skipped.
  ",
  				 dwarf_diename(in_die));
  			return -ENOENT;
  		}
b55a87ade   Masami Hiramatsu   perf probe: Remov...
975
  		pf->addr = addr;
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
976
977
978
979
  		pf->addr += pp->offset;
  		pr_debug("found inline addr: 0x%jx
  ",
  			 (uintmax_t)pf->addr);
db0d2c642   Masami Hiramatsu   perf probe: Searc...
980
  		ret = call_probe_finder(in_die, pf);
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
981
  	}
e92b85e1f   Masami Hiramatsu   perf probe: Use l...
982

db0d2c642   Masami Hiramatsu   perf probe: Searc...
983
  	return ret;
e92b85e1f   Masami Hiramatsu   perf probe: Use l...
984
  }
804b36068   Masami Hiramatsu   perf probe: Use e...
985

db0d2c642   Masami Hiramatsu   perf probe: Searc...
986
987
988
989
990
  /* Callback parameter with return value for libdw */
  struct dwarf_callback_param {
  	void *data;
  	int retval;
  };
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
991
  /* Search function from function name */
e92b85e1f   Masami Hiramatsu   perf probe: Use l...
992
  static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
993
  {
b55a87ade   Masami Hiramatsu   perf probe: Remov...
994
995
  	struct dwarf_callback_param *param = data;
  	struct probe_finder *pf = param->data;
4235b0454   Masami Hiramatsu   perf probe: Intro...
996
  	struct perf_probe_point *pp = &pf->pev->point;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
997

e92b85e1f   Masami Hiramatsu   perf probe: Use l...
998
  	/* Check tag and diename */
0dbb1cac1   Masami Hiramatsu   perf probe: Fix f...
999
  	if (!die_is_func_def(sp_die) ||
4c8593512   Masami Hiramatsu   perf probe: Suppo...
1000
  	    !die_match_name(sp_die, pp->function))
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1001
  		return DWARF_CB_OK;
e92b85e1f   Masami Hiramatsu   perf probe: Use l...
1002

7d21635ac   Masami Hiramatsu   perf probe: Fix t...
1003
1004
1005
  	/* Check declared file */
  	if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
  		return DWARF_CB_OK;
f8da4b515   Masami Hiramatsu   perf probe: Ignor...
1006
1007
1008
  	pr_debug("Matched function: %s [%lx]
  ", dwarf_diename(sp_die),
  		 (unsigned long)dwarf_dieoffset(sp_die));
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
1009
  	pf->fname = dwarf_decl_file(sp_die);
e92b85e1f   Masami Hiramatsu   perf probe: Use l...
1010
  	if (pp->line) { /* Function relative line */
e92b85e1f   Masami Hiramatsu   perf probe: Use l...
1011
1012
  		dwarf_decl_line(sp_die, &pf->lno);
  		pf->lno += pp->line;
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1013
  		param->retval = find_probe_point_by_line(pf);
e1ecbbc3f   Masami Hiramatsu   perf probe: Fix t...
1014
1015
1016
  	} else if (die_is_func_instance(sp_die)) {
  		/* Instances always have the entry address */
  		dwarf_entrypc(sp_die, &pf->addr);
0ad45b33c   Masami Hiramatsu   perf probe: Skip ...
1017
1018
1019
1020
1021
1022
  		/* But in some case the entry address is 0 */
  		if (pf->addr == 0) {
  			pr_debug("%s has no entry PC. Skipped
  ",
  				 dwarf_diename(sp_die));
  			param->retval = 0;
e92b85e1f   Masami Hiramatsu   perf probe: Use l...
1023
  		/* Real function */
0ad45b33c   Masami Hiramatsu   perf probe: Skip ...
1024
  		} else if (pp->lazy_line)
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1025
  			param->retval = find_probe_point_lazy(sp_die, pf);
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
1026
  		else {
e47392bf9   Ravi Bangoria   perf uprobe: Skip...
1027
  			skip_prologue(sp_die, pf);
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
1028
1029
  			pf->addr += pp->offset;
  			/* TODO: Check the address in this function */
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1030
  			param->retval = call_probe_finder(sp_die, pf);
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
1031
  		}
4c8593512   Masami Hiramatsu   perf probe: Suppo...
1032
  	} else if (!probe_conf.no_inlines) {
e92b85e1f   Masami Hiramatsu   perf probe: Use l...
1033
  		/* Inlined function: search instances */
db0d2c642   Masami Hiramatsu   perf probe: Searc...
1034
1035
  		param->retval = die_walk_instances(sp_die,
  					probe_point_inline_cb, (void *)pf);
4c8593512   Masami Hiramatsu   perf probe: Suppo...
1036
  		/* This could be a non-existed inline definition */
f8da4b515   Masami Hiramatsu   perf probe: Ignor...
1037
  		if (param->retval == -ENOENT)
4c8593512   Masami Hiramatsu   perf probe: Suppo...
1038
1039
1040
1041
1042
1043
1044
1045
  			param->retval = 0;
  	}
  
  	/* We need to find other candidates */
  	if (strisglob(pp->function) && param->retval >= 0) {
  		param->retval = 0;	/* We have to clear the result */
  		return DWARF_CB_OK;
  	}
e92b85e1f   Masami Hiramatsu   perf probe: Use l...
1046

b55a87ade   Masami Hiramatsu   perf probe: Remov...
1047
  	return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
1048
  }
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1049
  static int find_probe_point_by_func(struct probe_finder *pf)
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
1050
  {
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1051
1052
1053
1054
  	struct dwarf_callback_param _param = {.data = (void *)pf,
  					      .retval = 0};
  	dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
  	return _param.retval;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
1055
  }
cd25f8bc2   Lin Ming   perf probe: Add f...
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
  struct pubname_callback_param {
  	char *function;
  	char *file;
  	Dwarf_Die *cu_die;
  	Dwarf_Die *sp_die;
  	int found;
  };
  
  static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
  {
  	struct pubname_callback_param *param = data;
  
  	if (dwarf_offdie(dbg, gl->die_offset, param->sp_die)) {
  		if (dwarf_tag(param->sp_die) != DW_TAG_subprogram)
  			return DWARF_CB_OK;
4c8593512   Masami Hiramatsu   perf probe: Suppo...
1071
  		if (die_match_name(param->sp_die, param->function)) {
cd25f8bc2   Lin Ming   perf probe: Add f...
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
  			if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die))
  				return DWARF_CB_OK;
  
  			if (param->file &&
  			    strtailcmp(param->file, dwarf_decl_file(param->sp_die)))
  				return DWARF_CB_OK;
  
  			param->found = 1;
  			return DWARF_CB_ABORT;
  		}
  	}
  
  	return DWARF_CB_OK;
  }
270bde1e7   Hemant Kumar   perf probe: Searc...
1086
  static int debuginfo__find_probe_location(struct debuginfo *dbg,
ff7417835   Masami Hiramatsu   perf probe: Intro...
1087
  				  struct probe_finder *pf)
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
1088
  {
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1089
  	struct perf_probe_point *pp = &pf->pev->point;
804b36068   Masami Hiramatsu   perf probe: Use e...
1090
1091
1092
  	Dwarf_Off off, noff;
  	size_t cuhl;
  	Dwarf_Die *diep;
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1093
  	int ret = 0;
804b36068   Masami Hiramatsu   perf probe: Use e...
1094

804b36068   Masami Hiramatsu   perf probe: Use e...
1095
  	off = 0;
5a62257a3   Masami Hiramatsu   perf probe: Repla...
1096
1097
1098
  	pf->lcache = intlist__new(NULL);
  	if (!pf->lcache)
  		return -ENOMEM;
cd25f8bc2   Lin Ming   perf probe: Add f...
1099
1100
  
  	/* Fastpath: lookup by function name from .debug_pubnames section */
4c8593512   Masami Hiramatsu   perf probe: Suppo...
1101
  	if (pp->function && !strisglob(pp->function)) {
cd25f8bc2   Lin Ming   perf probe: Add f...
1102
1103
1104
1105
1106
  		struct pubname_callback_param pubname_param = {
  			.function = pp->function,
  			.file	  = pp->file,
  			.cu_die	  = &pf->cu_die,
  			.sp_die	  = &pf->sp_die,
2b348a779   Lin Ming   perf probe: Fix t...
1107
  			.found	  = 0,
cd25f8bc2   Lin Ming   perf probe: Add f...
1108
1109
1110
1111
  		};
  		struct dwarf_callback_param probe_param = {
  			.data = pf,
  		};
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
1112
  		dwarf_getpubnames(dbg->dbg, pubname_search_cb,
ff7417835   Masami Hiramatsu   perf probe: Intro...
1113
  				  &pubname_param, 0);
cd25f8bc2   Lin Ming   perf probe: Add f...
1114
1115
1116
1117
1118
1119
  		if (pubname_param.found) {
  			ret = probe_point_search_cb(&pf->sp_die, &probe_param);
  			if (ret)
  				goto found;
  		}
  	}
804b36068   Masami Hiramatsu   perf probe: Use e...
1120
  	/* Loop on CUs (Compilation Unit) */
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
1121
  	while (!dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
1122
  		/* Get the DIE(Debugging Information Entry) of this CU */
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
1123
  		diep = dwarf_offdie(dbg->dbg, off + cuhl, &pf->cu_die);
804b36068   Masami Hiramatsu   perf probe: Use e...
1124
1125
  		if (!diep)
  			continue;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
1126
1127
1128
  
  		/* Check if target file is included. */
  		if (pp->file)
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1129
  			pf->fname = cu_find_realpath(&pf->cu_die, pp->file);
804b36068   Masami Hiramatsu   perf probe: Use e...
1130
  		else
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1131
  			pf->fname = NULL;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
1132

cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1133
  		if (!pp->file || pf->fname) {
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
1134
  			if (pp->function)
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1135
  				ret = find_probe_point_by_func(pf);
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
1136
  			else if (pp->lazy_line)
f19e80c64   He Kuang   perf probe: Fix s...
1137
  				ret = find_probe_point_lazy(&pf->cu_die, pf);
b0ef07324   Masami Hiramatsu   perf/probes: Supp...
1138
  			else {
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1139
1140
  				pf->lno = pp->line;
  				ret = find_probe_point_by_line(pf);
b0ef07324   Masami Hiramatsu   perf/probes: Supp...
1141
  			}
8635bf6ea   Arnaldo Carvalho de Melo   perf probe: Remov...
1142
  			if (ret < 0)
fbee632d0   Arnaldo Carvalho de Melo   perf probe: Fix e...
1143
  				break;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
1144
  		}
804b36068   Masami Hiramatsu   perf probe: Use e...
1145
  		off = noff;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
1146
  	}
cd25f8bc2   Lin Ming   perf probe: Add f...
1147
1148
  
  found:
5a62257a3   Masami Hiramatsu   perf probe: Repla...
1149
1150
  	intlist__delete(pf->lcache);
  	pf->lcache = NULL;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
1151

cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1152
1153
  	return ret;
  }
270bde1e7   Hemant Kumar   perf probe: Searc...
1154
1155
1156
1157
1158
  /* Find probe points from debuginfo */
  static int debuginfo__find_probes(struct debuginfo *dbg,
  				  struct probe_finder *pf)
  {
  	int ret = 0;
270bde1e7   Hemant Kumar   perf probe: Searc...
1159
1160
  	Elf *elf;
  	GElf_Ehdr ehdr;
270bde1e7   Hemant Kumar   perf probe: Searc...
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
  
  	if (pf->cfi_eh || pf->cfi_dbg)
  		return debuginfo__find_probe_location(dbg, pf);
  
  	/* Get the call frame information from this dwarf */
  	elf = dwarf_getelf(dbg->dbg);
  	if (elf == NULL)
  		return -EINVAL;
  
  	if (gelf_getehdr(elf, &ehdr) == NULL)
  		return -EINVAL;
293d5b439   Masami Hiramatsu   perf probe: Suppo...
1172
1173
1174
1175
1176
1177
1178
1179
1180
  	pf->machine = ehdr.e_machine;
  
  #if _ELFUTILS_PREREQ(0, 142)
  	do {
  		GElf_Shdr shdr;
  
  		if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
  		    shdr.sh_type == SHT_PROGBITS)
  			pf->cfi_eh = dwarf_getcfi_elf(elf);
270bde1e7   Hemant Kumar   perf probe: Searc...
1181

293d5b439   Masami Hiramatsu   perf probe: Suppo...
1182
1183
  		pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
  	} while (0);
270bde1e7   Hemant Kumar   perf probe: Searc...
1184
1185
1186
1187
1188
  #endif
  
  	ret = debuginfo__find_probe_location(dbg, pf);
  	return ret;
  }
7969ec772   Masami Hiramatsu   perf probe: Suppo...
1189
1190
1191
  struct local_vars_finder {
  	struct probe_finder *pf;
  	struct perf_probe_arg *args;
f8bffbf12   Masami Hiramatsu   perf probe: Suppo...
1192
  	bool vars;
7969ec772   Masami Hiramatsu   perf probe: Suppo...
1193
1194
1195
1196
1197
1198
1199
1200
1201
  	int max_args;
  	int nargs;
  	int ret;
  };
  
  /* Collect available variables in this scope */
  static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
  {
  	struct local_vars_finder *vf = data;
3d918a12a   Masami Hiramatsu   perf probe: Find ...
1202
  	struct probe_finder *pf = vf->pf;
7969ec772   Masami Hiramatsu   perf probe: Suppo...
1203
1204
1205
1206
  	int tag;
  
  	tag = dwarf_tag(die_mem);
  	if (tag == DW_TAG_formal_parameter ||
f8bffbf12   Masami Hiramatsu   perf probe: Suppo...
1207
  	    (tag == DW_TAG_variable && vf->vars)) {
7969ec772   Masami Hiramatsu   perf probe: Suppo...
1208
  		if (convert_variable_location(die_mem, vf->pf->addr,
3d918a12a   Masami Hiramatsu   perf probe: Find ...
1209
  					      vf->pf->fb_ops, &pf->sp_die,
293d5b439   Masami Hiramatsu   perf probe: Suppo...
1210
  					      pf->machine, NULL) == 0) {
7969ec772   Masami Hiramatsu   perf probe: Suppo...
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
  			vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
  			if (vf->args[vf->nargs].var == NULL) {
  				vf->ret = -ENOMEM;
  				return DIE_FIND_CB_END;
  			}
  			pr_debug(" %s", vf->args[vf->nargs].var);
  			vf->nargs++;
  		}
  	}
  
  	if (dwarf_haspc(die_mem, vf->pf->addr))
  		return DIE_FIND_CB_CONTINUE;
  	else
  		return DIE_FIND_CB_SIBLING;
  }
  
  static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf,
  			     struct perf_probe_arg *args)
  {
  	Dwarf_Die die_mem;
  	int i;
  	int n = 0;
f8bffbf12   Masami Hiramatsu   perf probe: Suppo...
1233
  	struct local_vars_finder vf = {.pf = pf, .args = args, .vars = false,
7969ec772   Masami Hiramatsu   perf probe: Suppo...
1234
1235
1236
1237
  				.max_args = MAX_PROBE_ARGS, .ret = 0};
  
  	for (i = 0; i < pf->pev->nargs; i++) {
  		/* var never be NULL */
f8bffbf12   Masami Hiramatsu   perf probe: Suppo...
1238
1239
1240
  		if (strcmp(pf->pev->args[i].var, PROBE_ARG_VARS) == 0)
  			vf.vars = true;
  		else if (strcmp(pf->pev->args[i].var, PROBE_ARG_PARAMS) != 0) {
7969ec772   Masami Hiramatsu   perf probe: Suppo...
1241
1242
1243
  			/* Copy normal argument */
  			args[n] = pf->pev->args[i];
  			n++;
f8bffbf12   Masami Hiramatsu   perf probe: Suppo...
1244
  			continue;
7969ec772   Masami Hiramatsu   perf probe: Suppo...
1245
  		}
f8bffbf12   Masami Hiramatsu   perf probe: Suppo...
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
  		pr_debug("Expanding %s into:", pf->pev->args[i].var);
  		vf.nargs = n;
  		/* Special local variables */
  		die_find_child(sc_die, copy_variables_cb, (void *)&vf,
  			       &die_mem);
  		pr_debug(" (%d)
  ", vf.nargs - n);
  		if (vf.ret < 0)
  			return vf.ret;
  		n = vf.nargs;
7969ec772   Masami Hiramatsu   perf probe: Suppo...
1256
1257
1258
  	}
  	return n;
  }
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1259
  /* Add a found probe point into trace event list */
221d06118   Masami Hiramatsu   perf probe: Fix t...
1260
  static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1261
1262
1263
  {
  	struct trace_event_finder *tf =
  			container_of(pf, struct trace_event_finder, pf);
6cca13bdf   Masami Hiramatsu   perf probe: Impro...
1264
  	struct perf_probe_point *pp = &pf->pev->point;
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1265
  	struct probe_trace_event *tev;
092b1f0b5   Wang Nan   perf probe: Clear...
1266
  	struct perf_probe_arg *args = NULL;
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
  	int ret, i;
  
  	/* Check number of tevs */
  	if (tf->ntevs == tf->max_tevs) {
  		pr_warning("Too many( > %d) probe point found.
  ",
  			   tf->max_tevs);
  		return -ERANGE;
  	}
  	tev = &tf->tevs[tf->ntevs++];
221d06118   Masami Hiramatsu   perf probe: Fix t...
1277
  	/* Trace point should be converted from subprogram DIE */
576b52372   Masami Hiramatsu   perf probe: Fix p...
1278
  	ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr,
6cca13bdf   Masami Hiramatsu   perf probe: Impro...
1279
  				     pp->retprobe, pp->function, &tev->point);
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1280
  	if (ret < 0)
092b1f0b5   Wang Nan   perf probe: Clear...
1281
  		goto end;
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1282

4c8593512   Masami Hiramatsu   perf probe: Suppo...
1283
  	tev->point.realname = strdup(dwarf_diename(sc_die));
092b1f0b5   Wang Nan   perf probe: Clear...
1284
1285
1286
1287
  	if (!tev->point.realname) {
  		ret = -ENOMEM;
  		goto end;
  	}
4c8593512   Masami Hiramatsu   perf probe: Suppo...
1288

cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1289
1290
1291
  	pr_debug("Probe point found: %s+%lu
  ", tev->point.symbol,
  		 tev->point.offset);
7969ec772   Masami Hiramatsu   perf probe: Suppo...
1292
1293
  	/* Expand special probe argument if exist */
  	args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS);
092b1f0b5   Wang Nan   perf probe: Clear...
1294
1295
1296
1297
  	if (args == NULL) {
  		ret = -ENOMEM;
  		goto end;
  	}
7969ec772   Masami Hiramatsu   perf probe: Suppo...
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
  
  	ret = expand_probe_args(sc_die, pf, args);
  	if (ret < 0)
  		goto end;
  
  	tev->nargs = ret;
  	tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
  	if (tev->args == NULL) {
  		ret = -ENOMEM;
  		goto end;
  	}
  
  	/* Find each argument */
  	for (i = 0; i < tev->nargs; i++) {
  		pf->pvar = &args[i];
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1313
  		pf->tvar = &tev->args[i];
221d06118   Masami Hiramatsu   perf probe: Fix t...
1314
1315
  		/* Variable should be found from scope DIE */
  		ret = find_variable(sc_die, pf);
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1316
  		if (ret != 0)
7969ec772   Masami Hiramatsu   perf probe: Suppo...
1317
  			break;
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1318
  	}
7969ec772   Masami Hiramatsu   perf probe: Suppo...
1319
  end:
092b1f0b5   Wang Nan   perf probe: Clear...
1320
1321
1322
1323
  	if (ret) {
  		clear_probe_trace_event(tev);
  		tf->ntevs--;
  	}
7969ec772   Masami Hiramatsu   perf probe: Suppo...
1324
1325
  	free(args);
  	return ret;
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1326
1327
1328
  }
  
  /* Find probe_trace_events specified by perf_probe_event from debuginfo */
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
1329
  int debuginfo__find_trace_events(struct debuginfo *dbg,
ff7417835   Masami Hiramatsu   perf probe: Intro...
1330
  				 struct perf_probe_event *pev,
ddb2f58f9   Masami Hiramatsu   perf probe: Intro...
1331
  				 struct probe_trace_event **tevs)
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1332
1333
1334
  {
  	struct trace_event_finder tf = {
  			.pf = {.pev = pev, .callback = add_probe_trace_event},
ddb2f58f9   Masami Hiramatsu   perf probe: Intro...
1335
  			.max_tevs = probe_conf.max_probes, .mod = dbg->mod};
0196e787c   Masami Hiramatsu   perf probe: Fix m...
1336
  	int ret, i;
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1337
1338
  
  	/* Allocate result tevs array */
ddb2f58f9   Masami Hiramatsu   perf probe: Intro...
1339
  	*tevs = zalloc(sizeof(struct probe_trace_event) * tf.max_tevs);
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1340
1341
1342
1343
1344
  	if (*tevs == NULL)
  		return -ENOMEM;
  
  	tf.tevs = *tevs;
  	tf.ntevs = 0;
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
1345
  	ret = debuginfo__find_probes(dbg, &tf.pf);
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1346
  	if (ret < 0) {
0196e787c   Masami Hiramatsu   perf probe: Fix m...
1347
1348
  		for (i = 0; i < tf.ntevs; i++)
  			clear_probe_trace_event(&tf.tevs[i]);
046625231   Arnaldo Carvalho de Melo   perf tools: Intro...
1349
  		zfree(tevs);
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1350
1351
1352
1353
1354
  		return ret;
  	}
  
  	return (ret < 0) ? ret : tf.ntevs;
  }
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1355
1356
1357
1358
1359
  /* Collect available variables in this scope */
  static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
  {
  	struct available_var_finder *af = data;
  	struct variable_list *vl;
bf4d5f25c   Masami Hiramatsu   perf probe: Check...
1360
  	struct strbuf buf = STRBUF_INIT;
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1361
1362
1363
1364
1365
1366
1367
1368
  	int tag, ret;
  
  	vl = &af->vls[af->nvls - 1];
  
  	tag = dwarf_tag(die_mem);
  	if (tag == DW_TAG_formal_parameter ||
  	    tag == DW_TAG_variable) {
  		ret = convert_variable_location(die_mem, af->pf.addr,
3d918a12a   Masami Hiramatsu   perf probe: Find ...
1369
  						af->pf.fb_ops, &af->pf.sp_die,
293d5b439   Masami Hiramatsu   perf probe: Suppo...
1370
  						af->pf.machine, NULL);
349e8d261   He Kuang   perf probe: Add -...
1371
1372
1373
  		if (ret == 0 || ret == -ERANGE) {
  			int ret2;
  			bool externs = !af->child;
fb9596d17   He Kuang   perf probe: Remov...
1374

bf4d5f25c   Masami Hiramatsu   perf probe: Check...
1375
1376
  			if (strbuf_init(&buf, 64) < 0)
  				goto error;
349e8d261   He Kuang   perf probe: Add -...
1377
1378
  
  			if (probe_conf.show_location_range) {
bf4d5f25c   Masami Hiramatsu   perf probe: Check...
1379
1380
1381
1382
1383
1384
1385
  				if (!externs)
  					ret2 = strbuf_add(&buf,
  						ret ? "[INV]\t" : "[VAL]\t", 6);
  				else
  					ret2 = strbuf_add(&buf, "[EXT]\t", 6);
  				if (ret2)
  					goto error;
349e8d261   He Kuang   perf probe: Add -...
1386
1387
1388
1389
1390
1391
  			}
  
  			ret2 = die_get_varname(die_mem, &buf);
  
  			if (!ret2 && probe_conf.show_location_range &&
  				!externs) {
bf4d5f25c   Masami Hiramatsu   perf probe: Check...
1392
1393
  				if (strbuf_addch(&buf, '\t') < 0)
  					goto error;
349e8d261   He Kuang   perf probe: Add -...
1394
1395
1396
1397
1398
1399
1400
  				ret2 = die_get_var_range(&af->pf.sp_die,
  							die_mem, &buf);
  			}
  
  			pr_debug("Add new var: %s
  ", buf.buf);
  			if (ret2 == 0) {
fb9596d17   He Kuang   perf probe: Remov...
1401
1402
  				strlist__add(vl->vars,
  					strbuf_detach(&buf, NULL));
bf4d5f25c   Masami Hiramatsu   perf probe: Check...
1403
1404
  			}
  			strbuf_release(&buf);
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1405
1406
  		}
  	}
fb8c5a56c   Masami Hiramatsu   perf probe: Show ...
1407
  	if (af->child && dwarf_haspc(die_mem, af->pf.addr))
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1408
1409
1410
  		return DIE_FIND_CB_CONTINUE;
  	else
  		return DIE_FIND_CB_SIBLING;
bf4d5f25c   Masami Hiramatsu   perf probe: Check...
1411
1412
1413
1414
1415
  error:
  	strbuf_release(&buf);
  	pr_debug("Error in strbuf
  ");
  	return DIE_FIND_CB_END;
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1416
1417
1418
  }
  
  /* Add a found vars into available variables list */
221d06118   Masami Hiramatsu   perf probe: Fix t...
1419
  static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1420
1421
1422
  {
  	struct available_var_finder *af =
  			container_of(pf, struct available_var_finder, pf);
6cca13bdf   Masami Hiramatsu   perf probe: Impro...
1423
  	struct perf_probe_point *pp = &pf->pev->point;
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1424
  	struct variable_list *vl;
f182e3e13   Masami Hiramatsu   perf probe: Avoid...
1425
1426
  	Dwarf_Die die_mem;
  	int ret;
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1427
1428
1429
1430
1431
1432
1433
1434
  
  	/* Check number of tevs */
  	if (af->nvls == af->max_vls) {
  		pr_warning("Too many( > %d) probe point found.
  ", af->max_vls);
  		return -ERANGE;
  	}
  	vl = &af->vls[af->nvls++];
221d06118   Masami Hiramatsu   perf probe: Fix t...
1435
  	/* Trace point should be converted from subprogram DIE */
576b52372   Masami Hiramatsu   perf probe: Fix p...
1436
  	ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr,
6cca13bdf   Masami Hiramatsu   perf probe: Impro...
1437
  				     pp->retprobe, pp->function, &vl->point);
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1438
1439
1440
1441
1442
1443
1444
1445
  	if (ret < 0)
  		return ret;
  
  	pr_debug("Probe point found: %s+%lu
  ", vl->point.symbol,
  		 vl->point.offset);
  
  	/* Find local variables */
4a77e2183   Arnaldo Carvalho de Melo   perf strlist: Mak...
1446
  	vl->vars = strlist__new(NULL, NULL);
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1447
1448
  	if (vl->vars == NULL)
  		return -ENOMEM;
fb8c5a56c   Masami Hiramatsu   perf probe: Show ...
1449
  	af->child = true;
221d06118   Masami Hiramatsu   perf probe: Fix t...
1450
  	die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem);
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1451

fb8c5a56c   Masami Hiramatsu   perf probe: Show ...
1452
  	/* Find external variables */
ddb2f58f9   Masami Hiramatsu   perf probe: Intro...
1453
  	if (!probe_conf.show_ext_vars)
fb8c5a56c   Masami Hiramatsu   perf probe: Show ...
1454
  		goto out;
ddb2f58f9   Masami Hiramatsu   perf probe: Intro...
1455
  	/* Don't need to search child DIE for external vars. */
fb8c5a56c   Masami Hiramatsu   perf probe: Show ...
1456
  	af->child = false;
f182e3e13   Masami Hiramatsu   perf probe: Avoid...
1457
  	die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem);
fb8c5a56c   Masami Hiramatsu   perf probe: Show ...
1458
1459
  
  out:
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1460
1461
1462
1463
1464
1465
1466
  	if (strlist__empty(vl->vars)) {
  		strlist__delete(vl->vars);
  		vl->vars = NULL;
  	}
  
  	return ret;
  }
69e96eaa4   Masami Hiramatsu   perf probe: Impro...
1467
1468
1469
1470
1471
  /*
   * Find available variables at given probe point
   * Return the number of found probe points. Return 0 if there is no
   * matched probe point. Return <0 if an error occurs.
   */
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
1472
  int debuginfo__find_available_vars_at(struct debuginfo *dbg,
ff7417835   Masami Hiramatsu   perf probe: Intro...
1473
  				      struct perf_probe_event *pev,
ddb2f58f9   Masami Hiramatsu   perf probe: Intro...
1474
  				      struct variable_list **vls)
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1475
1476
1477
  {
  	struct available_var_finder af = {
  			.pf = {.pev = pev, .callback = add_available_vars},
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
1478
  			.mod = dbg->mod,
ddb2f58f9   Masami Hiramatsu   perf probe: Intro...
1479
  			.max_vls = probe_conf.max_probes};
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1480
1481
1482
  	int ret;
  
  	/* Allocate result vls array */
ddb2f58f9   Masami Hiramatsu   perf probe: Intro...
1483
  	*vls = zalloc(sizeof(struct variable_list) * af.max_vls);
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1484
1485
1486
1487
1488
  	if (*vls == NULL)
  		return -ENOMEM;
  
  	af.vls = *vls;
  	af.nvls = 0;
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
1489
  	ret = debuginfo__find_probes(dbg, &af.pf);
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1490
1491
1492
  	if (ret < 0) {
  		/* Free vlist for error */
  		while (af.nvls--) {
74cf249d5   Arnaldo Carvalho de Melo   perf tools: Use z...
1493
  			zfree(&af.vls[af.nvls].point.symbol);
f5385650c   Arnaldo Carvalho de Melo   perf tools: No ne...
1494
  			strlist__delete(af.vls[af.nvls].vars);
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1495
  		}
046625231   Arnaldo Carvalho de Melo   perf tools: Intro...
1496
  		zfree(vls);
cf6eb489e   Masami Hiramatsu   perf probe: Show ...
1497
1498
1499
1500
  		return ret;
  	}
  
  	return (ret < 0) ? ret : af.nvls;
4ea42b181   Masami Hiramatsu   perf: Add perf pr...
1501
  }
9b239a12b   Masami Hiramatsu   perf probe: Show ...
1502
  /* For the kernel module, we need a special code to get a DIE */
613f050d6   Masami Hiramatsu   perf probe: Fix t...
1503
1504
  int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
  				bool adjust_offset)
9b239a12b   Masami Hiramatsu   perf probe: Show ...
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
  {
  	int n, i;
  	Elf32_Word shndx;
  	Elf_Scn *scn;
  	Elf *elf;
  	GElf_Shdr mem, *shdr;
  	const char *p;
  
  	elf = dwfl_module_getelf(dbg->mod, &dbg->bias);
  	if (!elf)
  		return -EINVAL;
  
  	/* Get the number of relocations */
  	n = dwfl_module_relocations(dbg->mod);
  	if (n < 0)
  		return -ENOENT;
  	/* Search the relocation related .text section */
  	for (i = 0; i < n; i++) {
  		p = dwfl_module_relocation_info(dbg->mod, i, &shndx);
  		if (strcmp(p, ".text") == 0) {
  			/* OK, get the section header */
  			scn = elf_getscn(elf, shndx);
  			if (!scn)
  				return -ENOENT;
  			shdr = gelf_getshdr(scn, &mem);
  			if (!shdr)
  				return -ENOENT;
  			*offs = shdr->sh_addr;
613f050d6   Masami Hiramatsu   perf probe: Fix t...
1533
1534
  			if (adjust_offset)
  				*offs -= shdr->sh_offset;
9b239a12b   Masami Hiramatsu   perf probe: Show ...
1535
1536
1537
1538
  		}
  	}
  	return 0;
  }
fb1587d86   Masami Hiramatsu   perf probe: List ...
1539
  /* Reverse search */
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
1540
  int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
ff7417835   Masami Hiramatsu   perf probe: Intro...
1541
  				struct perf_probe_point *ppt)
fb1587d86   Masami Hiramatsu   perf probe: List ...
1542
1543
  {
  	Dwarf_Die cudie, spdie, indie;
e08cfd4bd   Masami Hiramatsu   perf probe: Fix t...
1544
1545
  	Dwarf_Addr _addr = 0, baseaddr = 0;
  	const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1546
  	int baseline = 0, lineno = 0, ret = 0;
fb1587d86   Masami Hiramatsu   perf probe: List ...
1547

d2d4edbeb   Masami Hiramatsu   perf probe: Fix t...
1548
  	/* We always need to relocate the address for aranges */
613f050d6   Masami Hiramatsu   perf probe: Fix t...
1549
  	if (debuginfo__get_text_offset(dbg, &baseaddr, false) == 0)
d2d4edbeb   Masami Hiramatsu   perf probe: Fix t...
1550
  		addr += baseaddr;
fb1587d86   Masami Hiramatsu   perf probe: List ...
1551
  	/* Find cu die */
0104fe69e   Masami Hiramatsu   perf probe: Remov...
1552
  	if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
0e43e5d22   Masami Hiramatsu   perf probe: Clean...
1553
1554
1555
  		pr_warning("Failed to find debug information for address %lx
  ",
  			   addr);
75ec5a245   Masami Hiramatsu   perf probe: Fix t...
1556
1557
1558
  		ret = -EINVAL;
  		goto end;
  	}
fb1587d86   Masami Hiramatsu   perf probe: List ...
1559

1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1560
1561
1562
  	/* Find a corresponding line (filename and lineno) */
  	cu_find_lineinfo(&cudie, addr, &fname, &lineno);
  	/* Don't care whether it failed or not */
fb1587d86   Masami Hiramatsu   perf probe: List ...
1563

1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1564
  	/* Find a corresponding function (name, baseline and baseaddr) */
e0d153c69   Masami Hiramatsu   perf-probe: Move ...
1565
  	if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) {
1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1566
  		/* Get function entry information */
e08cfd4bd   Masami Hiramatsu   perf probe: Fix t...
1567
1568
  		func = basefunc = dwarf_diename(&spdie);
  		if (!func ||
1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1569
  		    dwarf_entrypc(&spdie, &baseaddr) != 0 ||
e08cfd4bd   Masami Hiramatsu   perf probe: Fix t...
1570
1571
  		    dwarf_decl_line(&spdie, &baseline) != 0) {
  			lineno = 0;
1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1572
  			goto post;
e08cfd4bd   Masami Hiramatsu   perf probe: Fix t...
1573
  		}
1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1574

1b286bdd5   Masami Hiramatsu   perf probe: Fix t...
1575
  		fname = dwarf_decl_file(&spdie);
e08cfd4bd   Masami Hiramatsu   perf probe: Fix t...
1576
  		if (addr == (unsigned long)baseaddr) {
1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1577
1578
  			/* Function entry - Relative line number is 0 */
  			lineno = baseline;
e08cfd4bd   Masami Hiramatsu   perf probe: Fix t...
1579
1580
1581
1582
1583
1584
1585
  			goto post;
  		}
  
  		/* Track down the inline functions step by step */
  		while (die_find_top_inlinefunc(&spdie, (Dwarf_Addr)addr,
  						&indie)) {
  			/* There is an inline function */
1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1586
  			if (dwarf_entrypc(&indie, &_addr) == 0 &&
e08cfd4bd   Masami Hiramatsu   perf probe: Fix t...
1587
  			    _addr == addr) {
1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1588
1589
1590
  				/*
  				 * addr is at an inline function entry.
  				 * In this case, lineno should be the call-site
e08cfd4bd   Masami Hiramatsu   perf probe: Fix t...
1591
  				 * line number. (overwrite lineinfo)
1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1592
1593
  				 */
  				lineno = die_get_call_lineno(&indie);
e08cfd4bd   Masami Hiramatsu   perf probe: Fix t...
1594
1595
1596
  				fname = die_get_call_file(&indie);
  				break;
  			} else {
1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1597
1598
1599
1600
1601
1602
  				/*
  				 * addr is in an inline function body.
  				 * Since lineno points one of the lines
  				 * of the inline function, baseline should
  				 * be the entry line of the inline function.
  				 */
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1603
  				tmp = dwarf_diename(&indie);
e08cfd4bd   Masami Hiramatsu   perf probe: Fix t...
1604
1605
1606
1607
1608
  				if (!tmp ||
  				    dwarf_decl_line(&indie, &baseline) != 0)
  					break;
  				func = tmp;
  				spdie = indie;
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1609
  			}
fb1587d86   Masami Hiramatsu   perf probe: List ...
1610
  		}
e08cfd4bd   Masami Hiramatsu   perf probe: Fix t...
1611
1612
1613
1614
  		/* Verify the lineno and baseline are in a same file */
  		tmp = dwarf_decl_file(&spdie);
  		if (!tmp || strcmp(tmp, fname) != 0)
  			lineno = 0;
1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1615
1616
1617
1618
1619
1620
  	}
  
  post:
  	/* Make a relative line number or an offset */
  	if (lineno)
  		ppt->line = lineno - baseline;
e08cfd4bd   Masami Hiramatsu   perf probe: Fix t...
1621
  	else if (basefunc) {
1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1622
  		ppt->offset = addr - (unsigned long)baseaddr;
e08cfd4bd   Masami Hiramatsu   perf probe: Fix t...
1623
1624
  		func = basefunc;
  	}
1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1625
1626
1627
1628
  
  	/* Duplicate strings */
  	if (func) {
  		ppt->function = strdup(func);
02b95dadc   Masami Hiramatsu   perf probe: Remov...
1629
1630
1631
1632
  		if (ppt->function == NULL) {
  			ret = -ENOMEM;
  			goto end;
  		}
fb1587d86   Masami Hiramatsu   perf probe: List ...
1633
  	}
1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1634
1635
1636
  	if (fname) {
  		ppt->file = strdup(fname);
  		if (ppt->file == NULL) {
046625231   Arnaldo Carvalho de Melo   perf tools: Intro...
1637
  			zfree(&ppt->function);
1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1638
1639
1640
1641
  			ret = -ENOMEM;
  			goto end;
  		}
  	}
fb1587d86   Masami Hiramatsu   perf probe: List ...
1642
  end:
1d46ea2a6   Masami Hiramatsu   perf probe: Fix l...
1643
1644
  	if (ret == 0 && (fname || func))
  		ret = 1;	/* Found a point */
fb1587d86   Masami Hiramatsu   perf probe: List ...
1645
1646
  	return ret;
  }
f6c903f58   Masami Hiramatsu   perf probe: Show ...
1647
1648
1649
1650
  /* Add a line and store the src path */
  static int line_range_add_line(const char *src, unsigned int lineno,
  			       struct line_range *lr)
  {
7cf0b79e6   Masami Hiramatsu   perf probe: Fix e...
1651
  	/* Copy source path */
f6c903f58   Masami Hiramatsu   perf probe: Show ...
1652
  	if (!lr->path) {
7cf0b79e6   Masami Hiramatsu   perf probe: Fix e...
1653
1654
1655
  		lr->path = strdup(src);
  		if (lr->path == NULL)
  			return -ENOMEM;
f6c903f58   Masami Hiramatsu   perf probe: Show ...
1656
  	}
5a62257a3   Masami Hiramatsu   perf probe: Repla...
1657
  	return intlist__add(lr->line_list, lineno);
f6c903f58   Masami Hiramatsu   perf probe: Show ...
1658
  }
4cc9cec63   Masami Hiramatsu   perf probe: Intro...
1659
  static int line_range_walk_cb(const char *fname, int lineno,
1d037ca16   Irina Tirdea   perf tools: Use _...
1660
  			      Dwarf_Addr addr __maybe_unused,
4cc9cec63   Masami Hiramatsu   perf probe: Intro...
1661
  			      void *data)
f6c903f58   Masami Hiramatsu   perf probe: Show ...
1662
  {
4cc9cec63   Masami Hiramatsu   perf probe: Intro...
1663
  	struct line_finder *lf = data;
202c7c123   Namhyung Kim   perf probe: Fix -...
1664
  	int err;
f6c903f58   Masami Hiramatsu   perf probe: Show ...
1665

4cc9cec63   Masami Hiramatsu   perf probe: Intro...
1666
  	if ((strtailcmp(fname, lf->fname) != 0) ||
f6c903f58   Masami Hiramatsu   perf probe: Show ...
1667
  	    (lf->lno_s > lineno || lf->lno_e < lineno))
4cc9cec63   Masami Hiramatsu   perf probe: Intro...
1668
  		return 0;
f6c903f58   Masami Hiramatsu   perf probe: Show ...
1669

202c7c123   Namhyung Kim   perf probe: Fix -...
1670
1671
1672
  	err = line_range_add_line(fname, lineno, lf->lr);
  	if (err < 0 && err != -EEXIST)
  		return err;
f6c903f58   Masami Hiramatsu   perf probe: Show ...
1673

4cc9cec63   Masami Hiramatsu   perf probe: Intro...
1674
  	return 0;
f6c903f58   Masami Hiramatsu   perf probe: Show ...
1675
  }
fb1587d86   Masami Hiramatsu   perf probe: List ...
1676

631c9def8   Masami Hiramatsu   perf probe: Suppo...
1677
  /* Find line range from its line number */
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1678
  static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1679
  {
4cc9cec63   Masami Hiramatsu   perf probe: Intro...
1680
  	int ret;
f6c903f58   Masami Hiramatsu   perf probe: Show ...
1681

4cc9cec63   Masami Hiramatsu   perf probe: Intro...
1682
  	ret = die_walk_lines(sp_die ?: &lf->cu_die, line_range_walk_cb, lf);
f6c903f58   Masami Hiramatsu   perf probe: Show ...
1683

804b36068   Masami Hiramatsu   perf probe: Use e...
1684
  	/* Update status */
f6c903f58   Masami Hiramatsu   perf probe: Show ...
1685
  	if (ret >= 0)
5a62257a3   Masami Hiramatsu   perf probe: Repla...
1686
  		if (!intlist__empty(lf->lr->line_list))
f6c903f58   Masami Hiramatsu   perf probe: Show ...
1687
1688
1689
  			ret = lf->found = 1;
  		else
  			ret = 0;	/* Lines are not found */
804b36068   Masami Hiramatsu   perf probe: Use e...
1690
  	else {
046625231   Arnaldo Carvalho de Melo   perf tools: Intro...
1691
  		zfree(&lf->lr->path);
804b36068   Masami Hiramatsu   perf probe: Use e...
1692
  	}
f6c903f58   Masami Hiramatsu   perf probe: Show ...
1693
  	return ret;
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1694
  }
161a26b0c   Masami Hiramatsu   perf probe: Check...
1695
1696
  static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
  {
182c228eb   Masami Hiramatsu   perf probe: Fix t...
1697
  	int ret = find_line_range_by_line(in_die, data);
36c0c588b   Masami Hiramatsu   perf probe: Fix t...
1698
1699
1700
1701
  
  	/*
  	 * We have to check all instances of inlined function, because
  	 * some execution paths can be optimized out depends on the
182c228eb   Masami Hiramatsu   perf probe: Fix t...
1702
1703
  	 * function argument of instances. However, if an error occurs,
  	 * it should be handled by the caller.
36c0c588b   Masami Hiramatsu   perf probe: Fix t...
1704
  	 */
182c228eb   Masami Hiramatsu   perf probe: Fix t...
1705
  	return ret < 0 ? ret : 0;
161a26b0c   Masami Hiramatsu   perf probe: Check...
1706
  }
0dbb1cac1   Masami Hiramatsu   perf probe: Fix f...
1707
  /* Search function definition from function name */
e92b85e1f   Masami Hiramatsu   perf probe: Use l...
1708
  static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1709
  {
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1710
1711
  	struct dwarf_callback_param *param = data;
  	struct line_finder *lf = param->data;
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1712
  	struct line_range *lr = lf->lr;
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1713

7d21635ac   Masami Hiramatsu   perf probe: Fix t...
1714
1715
1716
  	/* Check declared file */
  	if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
  		return DWARF_CB_OK;
0dbb1cac1   Masami Hiramatsu   perf probe: Fix f...
1717
  	if (die_is_func_def(sp_die) &&
4c8593512   Masami Hiramatsu   perf probe: Suppo...
1718
  	    die_match_name(sp_die, lr->function)) {
e92b85e1f   Masami Hiramatsu   perf probe: Use l...
1719
1720
  		lf->fname = dwarf_decl_file(sp_die);
  		dwarf_decl_line(sp_die, &lr->offset);
804b36068   Masami Hiramatsu   perf probe: Use e...
1721
1722
  		pr_debug("fname: %s, lineno:%d
  ", lf->fname, lr->offset);
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1723
  		lf->lno_s = lr->offset + lr->start;
d3b63d7ae   Masami Hiramatsu   perf probe: Fix a...
1724
1725
1726
1727
  		if (lf->lno_s < 0)	/* Overflow */
  			lf->lno_s = INT_MAX;
  		lf->lno_e = lr->offset + lr->end;
  		if (lf->lno_e < 0)	/* Overflow */
804b36068   Masami Hiramatsu   perf probe: Use e...
1728
  			lf->lno_e = INT_MAX;
d3b63d7ae   Masami Hiramatsu   perf probe: Fix a...
1729
1730
  		pr_debug("New line range: %d to %d
  ", lf->lno_s, lf->lno_e);
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1731
1732
  		lr->start = lf->lno_s;
  		lr->end = lf->lno_e;
e1ecbbc3f   Masami Hiramatsu   perf probe: Fix t...
1733
  		if (!die_is_func_instance(sp_die))
db0d2c642   Masami Hiramatsu   perf probe: Searc...
1734
1735
1736
  			param->retval = die_walk_instances(sp_die,
  						line_range_inline_cb, lf);
  		else
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1737
1738
  			param->retval = find_line_range_by_line(sp_die, lf);
  		return DWARF_CB_ABORT;
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1739
  	}
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1740
  	return DWARF_CB_OK;
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1741
  }
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1742
  static int find_line_range_by_func(struct line_finder *lf)
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1743
  {
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1744
1745
1746
  	struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
  	dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
  	return param.retval;
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1747
  }
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
1748
  int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr)
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1749
  {
804b36068   Masami Hiramatsu   perf probe: Use e...
1750
  	struct line_finder lf = {.lr = lr, .found = 0};
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1751
  	int ret = 0;
804b36068   Masami Hiramatsu   perf probe: Use e...
1752
1753
1754
  	Dwarf_Off off = 0, noff;
  	size_t cuhl;
  	Dwarf_Die *diep;
6a330a3c8   Masami Hiramatsu   perf probe: Suppo...
1755
  	const char *comp_dir;
804b36068   Masami Hiramatsu   perf probe: Use e...
1756

cd25f8bc2   Lin Ming   perf probe: Add f...
1757
1758
1759
1760
1761
1762
1763
  	/* Fastpath: lookup by function name from .debug_pubnames section */
  	if (lr->function) {
  		struct pubname_callback_param pubname_param = {
  			.function = lr->function, .file = lr->file,
  			.cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0};
  		struct dwarf_callback_param line_range_param = {
  			.data = (void *)&lf, .retval = 0};
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
1764
  		dwarf_getpubnames(dbg->dbg, pubname_search_cb,
ff7417835   Masami Hiramatsu   perf probe: Intro...
1765
  				  &pubname_param, 0);
cd25f8bc2   Lin Ming   perf probe: Add f...
1766
1767
1768
1769
1770
1771
  		if (pubname_param.found) {
  			line_range_search_cb(&lf.sp_die, &line_range_param);
  			if (lf.found)
  				goto found;
  		}
  	}
804b36068   Masami Hiramatsu   perf probe: Use e...
1772
  	/* Loop on CUs (Compilation Unit) */
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1773
  	while (!lf.found && ret >= 0) {
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
1774
  		if (dwarf_nextcu(dbg->dbg, off, &noff, &cuhl,
ff7417835   Masami Hiramatsu   perf probe: Intro...
1775
  				 NULL, NULL, NULL) != 0)
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1776
1777
1778
  			break;
  
  		/* Get the DIE(Debugging Information Entry) of this CU */
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
1779
  		diep = dwarf_offdie(dbg->dbg, off + cuhl, &lf.cu_die);
804b36068   Masami Hiramatsu   perf probe: Use e...
1780
1781
  		if (!diep)
  			continue;
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1782
1783
1784
  
  		/* Check if target file is included. */
  		if (lr->file)
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
1785
  			lf.fname = cu_find_realpath(&lf.cu_die, lr->file);
804b36068   Masami Hiramatsu   perf probe: Use e...
1786
  		else
2a9c8c360   Masami Hiramatsu   perf probe: Add l...
1787
  			lf.fname = 0;
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1788

2a9c8c360   Masami Hiramatsu   perf probe: Add l...
1789
  		if (!lr->file || lf.fname) {
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1790
  			if (lr->function)
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1791
  				ret = find_line_range_by_func(&lf);
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1792
1793
  			else {
  				lf.lno_s = lr->start;
d3b63d7ae   Masami Hiramatsu   perf probe: Fix a...
1794
  				lf.lno_e = lr->end;
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1795
  				ret = find_line_range_by_line(NULL, &lf);
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1796
  			}
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1797
  		}
804b36068   Masami Hiramatsu   perf probe: Use e...
1798
  		off = noff;
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1799
  	}
6a330a3c8   Masami Hiramatsu   perf probe: Suppo...
1800

cd25f8bc2   Lin Ming   perf probe: Add f...
1801
  found:
6a330a3c8   Masami Hiramatsu   perf probe: Suppo...
1802
1803
1804
1805
1806
1807
1808
1809
1810
  	/* Store comp_dir */
  	if (lf.found) {
  		comp_dir = cu_get_comp_dir(&lf.cu_die);
  		if (comp_dir) {
  			lr->comp_dir = strdup(comp_dir);
  			if (!lr->comp_dir)
  				ret = -ENOMEM;
  		}
  	}
7cf0b79e6   Masami Hiramatsu   perf probe: Fix e...
1811
1812
  	pr_debug("path: %s
  ", lr->path);
b55a87ade   Masami Hiramatsu   perf probe: Remov...
1813
  	return (ret < 0) ? ret : lf.found;
631c9def8   Masami Hiramatsu   perf probe: Suppo...
1814
  }
09ed8975c   Naohiro Aota   perf probe: Find ...
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
  /*
   * Find a src file from a DWARF tag path. Prepend optional source path prefix
   * and chop off leading directories that do not exist. Result is passed back as
   * a newly allocated path on success.
   * Return 0 if file was found and readable, -errno otherwise.
   */
  int get_real_path(const char *raw_path, const char *comp_dir,
  			 char **new_path)
  {
  	const char *prefix = symbol_conf.source_prefix;
  
  	if (!prefix) {
  		if (raw_path[0] != '/' && comp_dir)
  			/* If not an absolute path, try to use comp_dir */
  			prefix = comp_dir;
  		else {
  			if (access(raw_path, R_OK) == 0) {
  				*new_path = strdup(raw_path);
  				return *new_path ? 0 : -ENOMEM;
  			} else
  				return -errno;
  		}
  	}
  
  	*new_path = malloc((strlen(prefix) + strlen(raw_path) + 2));
  	if (!*new_path)
  		return -ENOMEM;
  
  	for (;;) {
  		sprintf(*new_path, "%s/%s", prefix, raw_path);
  
  		if (access(*new_path, R_OK) == 0)
  			return 0;
  
  		if (!symbol_conf.source_prefix) {
  			/* In case of searching comp_dir, don't retry */
  			zfree(new_path);
  			return -errno;
  		}
  
  		switch (errno) {
  		case ENAMETOOLONG:
  		case ENOENT:
  		case EROFS:
  		case EFAULT:
  			raw_path = strchr(++raw_path, '/');
  			if (!raw_path) {
  				zfree(new_path);
  				return -ENOENT;
  			}
  			continue;
  
  		default:
  			zfree(new_path);
  			return -errno;
  		}
  	}
  }