probe-finder.c 32.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
/*
 * 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.
 *
 */

#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
34

35
#include "string.h"
36 37
#include "event.h"
#include "debug.h"
38
#include "util.h"
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
#include "probe-finder.h"


/*
 * Generic dwarf analysis helpers
 */

#define X86_32_MAX_REGS 8
const char *x86_32_regs_table[X86_32_MAX_REGS] = {
	"%ax",
	"%cx",
	"%dx",
	"%bx",
	"$stack",	/* Stack address instead of %sp */
	"%bp",
	"%si",
	"%di",
};

#define X86_64_MAX_REGS 16
const char *x86_64_regs_table[X86_64_MAX_REGS] = {
	"%ax",
	"%dx",
	"%cx",
	"%bx",
	"%si",
	"%di",
	"%bp",
	"%sp",
	"%r8",
	"%r9",
	"%r10",
	"%r11",
	"%r12",
	"%r13",
	"%r14",
	"%r15",
};

/* TODO: switching by dwarf address size */
#ifdef __x86_64__
#define ARCH_MAX_REGS X86_64_MAX_REGS
#define arch_regs_table x86_64_regs_table
#else
#define ARCH_MAX_REGS X86_32_MAX_REGS
#define arch_regs_table x86_32_regs_table
#endif

87 88 89
/* Kprobe tracer basic type is up to u64 */
#define MAX_BASIC_TYPE_BITS	64

90 91 92 93 94 95 96 97 98 99 100 101 102 103
/* Return architecture dependent register string (for kprobe-tracer) */
static const char *get_arch_regstr(unsigned int n)
{
	return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL;
}

/*
 * Compare the tail of two strings.
 * Return 0 if whole of either string is same as another's tail part.
 */
static int strtailcmp(const char *s1, const char *s2)
{
	int i1 = strlen(s1);
	int i2 = strlen(s2);
104
	while (--i1 >= 0 && --i2 >= 0) {
105 106 107 108 109 110
		if (s1[i1] != s2[i2])
			return s1[i1] - s2[i2];
	}
	return 0;
}

111 112 113
/* Line number list operations */

/* Add a line to line number list */
114
static int line_list__add_line(struct list_head *head, int line)
115 116 117 118 119 120 121 122 123 124
{
	struct line_node *ln;
	struct list_head *p;

	/* Reverse search, because new line will be the last one */
	list_for_each_entry_reverse(ln, head, list) {
		if (ln->line < line) {
			p = &ln->list;
			goto found;
		} else if (ln->line == line)	/* Already exist */
125
			return 1;
126 127 128 129 130
	}
	/* List is empty, or the smallest entry */
	p = head;
found:
	pr_debug("line list: add a line %u\n", line);
131 132 133
	ln = zalloc(sizeof(struct line_node));
	if (ln == NULL)
		return -ENOMEM;
134 135 136
	ln->line = line;
	INIT_LIST_HEAD(&ln->list);
	list_add(&ln->list, p);
137
	return 0;
138 139 140
}

/* Check if the line in line number list */
141
static int line_list__has_line(struct list_head *head, int line)
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
{
	struct line_node *ln;

	/* Reverse search, because new line will be the last one */
	list_for_each_entry(ln, head, list)
		if (ln->line == line)
			return 1;

	return 0;
}

/* Init line number list */
static void line_list__init(struct list_head *head)
{
	INIT_LIST_HEAD(head);
}

/* Free line number list */
static void line_list__free(struct list_head *head)
{
	struct line_node *ln;
	while (!list_empty(head)) {
		ln = list_first_entry(head, struct line_node, list);
		list_del(&ln->list);
		free(ln);
	}
}

/* Dwarf wrappers */

/* Find the realpath of the target file. */
static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
174
{
175 176
	Dwarf_Files *files;
	size_t nfiles, i;
177
	const char *src = NULL;
178 179 180
	int ret;

	if (!fname)
181
		return NULL;
182

183
	ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
184 185 186 187 188 189 190
	if (ret != 0)
		return NULL;

	for (i = 0; i < nfiles; i++) {
		src = dwarf_filesrc(files, i, NULL, NULL);
		if (strtailcmp(src, fname) == 0)
			break;
191
	}
192 193
	if (i == nfiles)
		return NULL;
194
	return src;
195 196
}

197 198 199 200 201
/* Compare diename and tname */
static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
{
	const char *name;
	name = dwarf_diename(dw_die);
202
	return name ? strcmp(tname, name) : -1;
203 204
}

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
/* Get type die, but skip qualifiers and typedef */
static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
{
	Dwarf_Attribute attr;
	int tag;

	do {
		if (dwarf_attr(vr_die, DW_AT_type, &attr) == NULL ||
		    dwarf_formref_die(&attr, die_mem) == NULL)
			return NULL;

		tag = dwarf_tag(die_mem);
		vr_die = die_mem;
	} while (tag == DW_TAG_const_type ||
		 tag == DW_TAG_restrict_type ||
		 tag == DW_TAG_volatile_type ||
		 tag == DW_TAG_shared_type ||
		 tag == DW_TAG_typedef);

	return die_mem;
}

227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
static bool die_is_signed_type(Dwarf_Die *tp_die)
{
	Dwarf_Attribute attr;
	Dwarf_Word ret;

	if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL ||
	    dwarf_formudata(&attr, &ret) != 0)
		return false;

	return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
		ret == DW_ATE_signed_fixed);
}

static int die_get_byte_size(Dwarf_Die *tp_die)
{
	Dwarf_Attribute attr;
	Dwarf_Word ret;

	if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL ||
	    dwarf_formudata(&attr, &ret) != 0)
		return 0;

	return (int)ret;
}

252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
/* Get data_member_location offset */
static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
{
	Dwarf_Attribute attr;
	Dwarf_Op *expr;
	size_t nexpr;
	int ret;

	if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
		return -ENOENT;

	if (dwarf_formudata(&attr, offs) != 0) {
		/* DW_AT_data_member_location should be DW_OP_plus_uconst */
		ret = dwarf_getlocation(&attr, &expr, &nexpr);
		if (ret < 0 || nexpr == 0)
			return -ENOENT;

		if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
			pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
				 expr[0].atom, nexpr);
			return -ENOTSUP;
		}
		*offs = (Dwarf_Word)expr[0].number;
	}
	return 0;
}

279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
/* Return values for die_find callbacks */
enum {
	DIE_FIND_CB_FOUND = 0,		/* End of Search */
	DIE_FIND_CB_CHILD = 1,		/* Search only children */
	DIE_FIND_CB_SIBLING = 2,	/* Search only siblings */
	DIE_FIND_CB_CONTINUE = 3,	/* Search children and siblings */
};

/* Search a child die */
static Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
				 int (*callback)(Dwarf_Die *, void *),
				 void *data, Dwarf_Die *die_mem)
{
	Dwarf_Die child_die;
	int ret;

	ret = dwarf_child(rt_die, die_mem);
	if (ret != 0)
		return NULL;

	do {
		ret = callback(die_mem, data);
		if (ret == DIE_FIND_CB_FOUND)
			return die_mem;

		if ((ret & DIE_FIND_CB_CHILD) &&
		    die_find_child(die_mem, callback, data, &child_die)) {
			memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
			return die_mem;
		}
	} while ((ret & DIE_FIND_CB_SIBLING) &&
		 dwarf_siblingof(die_mem, die_mem) == 0);

	return NULL;
}

315 316 317 318 319 320
struct __addr_die_search_param {
	Dwarf_Addr	addr;
	Dwarf_Die	*die_mem;
};

static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
321
{
322
	struct __addr_die_search_param *ad = data;
323

324 325 326 327 328 329 330
	if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
	    dwarf_haspc(fn_die, ad->addr)) {
		memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
		return DWARF_CB_ABORT;
	}
	return DWARF_CB_OK;
}
331

332
/* Search a real subprogram including this line, */
333 334
static Dwarf_Die *die_find_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr,
					   Dwarf_Die *die_mem)
335 336 337 338 339 340 341 342 343
{
	struct __addr_die_search_param ad;
	ad.addr = addr;
	ad.die_mem = die_mem;
	/* dwarf_getscopes can't find subprogram. */
	if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
		return NULL;
	else
		return die_mem;
344 345
}

346 347
/* die_find callback for inline function search */
static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
348
{
349
	Dwarf_Addr *addr = data;
350

351 352 353
	if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
	    dwarf_haspc(die_mem, *addr))
		return DIE_FIND_CB_FOUND;
354

355
	return DIE_FIND_CB_CONTINUE;
356 357
}

358 359 360
/* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */
static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
				      Dwarf_Die *die_mem)
361
{
362
	return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
363 364
}

365
static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
366
{
367 368
	const char *name = data;
	int tag;
369

370 371 372 373 374 375 376
	tag = dwarf_tag(die_mem);
	if ((tag == DW_TAG_formal_parameter ||
	     tag == DW_TAG_variable) &&
	    (die_compare_name(die_mem, name) == 0))
		return DIE_FIND_CB_FOUND;

	return DIE_FIND_CB_CONTINUE;
377 378
}

379
/* Find a variable called 'name' */
380 381
static Dwarf_Die *die_find_variable(Dwarf_Die *sp_die, const char *name,
				    Dwarf_Die *die_mem)
382
{
383 384
	return die_find_child(sp_die, __die_find_variable_cb, (void *)name,
			      die_mem);
385 386
}

387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
{
	const char *name = data;

	if ((dwarf_tag(die_mem) == DW_TAG_member) &&
	    (die_compare_name(die_mem, name) == 0))
		return DIE_FIND_CB_FOUND;

	return DIE_FIND_CB_SIBLING;
}

/* Find a member called 'name' */
static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
				  Dwarf_Die *die_mem)
{
	return die_find_child(st_die, __die_find_member_cb, (void *)name,
			      die_mem);
}

406 407 408 409 410
/*
 * Probe finder related functions
 */

/* Show a location */
411
static int convert_location(Dwarf_Op *op, struct probe_finder *pf)
412
{
413 414
	unsigned int regn;
	Dwarf_Word offs = 0;
415
	bool ref = false;
416
	const char *regs;
417
	struct kprobe_trace_arg *tvar = pf->tvar;
418 419

	/* If this is based on frame buffer, set the offset */
420
	if (op->atom == DW_OP_fbreg) {
421 422 423 424 425
		if (pf->fb_ops == NULL) {
			pr_warning("The attribute of frame base is not "
				   "supported.\n");
			return -ENOTSUP;
		}
426
		ref = true;
427 428 429
		offs = op->number;
		op = &pf->fb_ops[0];
	}
430

431 432 433
	if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
		regn = op->atom - DW_OP_breg0;
		offs += op->number;
434
		ref = true;
435 436 437 438 439
	} 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;
440
		ref = true;
441 442
	} else if (op->atom == DW_OP_regx) {
		regn = op->number;
443 444 445 446
	} else {
		pr_warning("DW_OP %x is not supported.\n", op->atom);
		return -ENOTSUP;
	}
447 448

	regs = get_arch_regstr(regn);
449 450 451 452
	if (!regs) {
		pr_warning("%u exceeds max register number.\n", regn);
		return -ERANGE;
	}
453

454 455 456 457
	tvar->value = strdup(regs);
	if (tvar->value == NULL)
		return -ENOMEM;

458
	if (ref) {
459 460 461
		tvar->ref = zalloc(sizeof(struct kprobe_trace_arg_ref));
		if (tvar->ref == NULL)
			return -ENOMEM;
462 463
		tvar->ref->offset = (long)offs;
	}
464
	return 0;
465 466
}

467 468
static int convert_variable_type(Dwarf_Die *vr_die,
				 struct kprobe_trace_arg *targ)
469 470 471 472 473
{
	Dwarf_Die type;
	char buf[16];
	int ret;

474 475 476 477 478
	if (die_get_real_type(vr_die, &type) == NULL) {
		pr_warning("Failed to get a type information of %s.\n",
			   dwarf_diename(vr_die));
		return -ENOENT;
	}
479 480 481 482 483

	ret = die_get_byte_size(&type) * 8;
	if (ret) {
		/* Check the bitwidth */
		if (ret > MAX_BASIC_TYPE_BITS) {
484 485 486
			pr_info("%s exceeds max-bitwidth."
				" Cut down to %d bits.\n",
				dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
487 488 489 490 491
			ret = MAX_BASIC_TYPE_BITS;
		}

		ret = snprintf(buf, 16, "%c%d",
			       die_is_signed_type(&type) ? 's' : 'u', ret);
492 493 494 495 496 497 498
		if (ret < 0 || ret >= 16) {
			if (ret >= 16)
				ret = -E2BIG;
			pr_warning("Failed to convert variable type: %s\n",
				   strerror(-ret));
			return ret;
		}
499 500 501
		targ->type = strdup(buf);
		if (targ->type == NULL)
			return -ENOMEM;
502
	}
503
	return 0;
504 505
}

506
static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
507
				    struct perf_probe_arg_field *field,
508 509
				    struct kprobe_trace_arg_ref **ref_ptr,
				    Dwarf_Die *die_mem)
510 511 512 513
{
	struct kprobe_trace_arg_ref *ref = *ref_ptr;
	Dwarf_Die type;
	Dwarf_Word offs;
514
	int ret;
515 516

	pr_debug("converting %s in %s\n", field->name, varname);
517 518 519 520
	if (die_get_real_type(vr_die, &type) == NULL) {
		pr_warning("Failed to get the type of %s.\n", varname);
		return -ENOENT;
	}
521 522 523

	/* Check the pointer and dereference */
	if (dwarf_tag(&type) == DW_TAG_pointer_type) {
524 525 526 527 528
		if (!field->ref) {
			pr_err("Semantic error: %s must be referred by '->'\n",
			       field->name);
			return -EINVAL;
		}
529
		/* Get the type pointed by this pointer */
530 531 532 533
		if (die_get_real_type(&type, &type) == NULL) {
			pr_warning("Failed to get the type of %s.\n", varname);
			return -ENOENT;
		}
534
		/* Verify it is a data structure  */
535 536 537 538
		if (dwarf_tag(&type) != DW_TAG_structure_type) {
			pr_warning("%s is not a data structure.\n", varname);
			return -EINVAL;
		}
539

540 541 542
		ref = zalloc(sizeof(struct kprobe_trace_arg_ref));
		if (ref == NULL)
			return -ENOMEM;
543 544 545 546 547
		if (*ref_ptr)
			(*ref_ptr)->next = ref;
		else
			*ref_ptr = ref;
	} else {
548
		/* Verify it is a data structure  */
549 550 551 552 553 554 555 556 557 558 559 560 561 562
		if (dwarf_tag(&type) != DW_TAG_structure_type) {
			pr_warning("%s is not a data structure.\n", varname);
			return -EINVAL;
		}
		if (field->ref) {
			pr_err("Semantic error: %s must be referred by '.'\n",
			       field->name);
			return -EINVAL;
		}
		if (!ref) {
			pr_warning("Structure on a register is not "
				   "supported yet.\n");
			return -ENOTSUP;
		}
563 564
	}

565 566 567 568 569
	if (die_find_member(&type, field->name, die_mem) == NULL) {
		pr_warning("%s(tyep:%s) has no member %s.\n", varname,
			   dwarf_diename(&type), field->name);
		return -EINVAL;
	}
570 571

	/* Get the offset of the field */
572 573
	ret = die_get_data_member_location(die_mem, &offs);
	if (ret < 0) {
574
		pr_warning("Failed to get the offset of %s.\n", field->name);
575
		return ret;
576
	}
577 578 579 580
	ref->offset += (long)offs;

	/* Converting next field */
	if (field->next)
581
		return convert_variable_fields(die_mem, field->name,
582
					field->next, &ref, die_mem);
583 584
	else
		return 0;
585 586
}

587
/* Show a variables in kprobe event format */
588
static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
589 590
{
	Dwarf_Attribute attr;
591
	Dwarf_Die die_mem;
592 593
	Dwarf_Op *expr;
	size_t nexpr;
594 595
	int ret;

596
	if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
597
		goto error;
598
	/* TODO: handle more than 1 exprs */
599
	ret = dwarf_getlocation_addr(&attr, pf->addr, &expr, &nexpr, 1);
600
	if (ret <= 0 || nexpr == 0)
601
		goto error;
602

603 604 605 606 607
	ret = convert_location(expr, pf);
	if (ret == 0 && pf->pvar->field) {
		ret = convert_variable_fields(vr_die, pf->pvar->var,
					      pf->pvar->field, &pf->tvar->ref,
					      &die_mem);
608 609
		vr_die = &die_mem;
	}
610
	if (ret == 0) {
611 612 613 614 615
		if (pf->pvar->type) {
			pf->tvar->type = strdup(pf->pvar->type);
			if (pf->tvar->type == NULL)
				ret = -ENOMEM;
		} else
616 617
			ret = convert_variable_type(vr_die, pf->tvar);
	}
618
	/* *expr will be cached in libdw. Don't free it. */
619
	return ret;
620
error:
621
	/* TODO: Support const_value */
622 623 624
	pr_err("Failed to find the location of %s at this address.\n"
	       " Perhaps, it has been optimized out.\n", pf->pvar->var);
	return -ENOENT;
625 626 627
}

/* Find a variable in a subprogram die */
628
static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
629
{
630
	Dwarf_Die vr_die;
631
	char buf[32], *ptr;
632
	int ret;
633

634 635
	/* TODO: Support arrays */
	if (pf->pvar->name)
636
		pf->tvar->name = strdup(pf->pvar->name);
637
	else {
638 639 640
		ret = synthesize_perf_probe_arg(pf->pvar, buf, 32);
		if (ret < 0)
			return ret;
641 642 643
		ptr = strchr(buf, ':');	/* Change type separator to _ */
		if (ptr)
			*ptr = '_';
644
		pf->tvar->name = strdup(buf);
645
	}
646 647
	if (pf->tvar->name == NULL)
		return -ENOMEM;
648 649

	if (!is_c_varname(pf->pvar->var)) {
650
		/* Copy raw parameters */
651 652 653 654 655
		pf->tvar->value = strdup(pf->pvar->var);
		if (pf->tvar->value == NULL)
			return -ENOMEM;
		else
			return 0;
656
	}
657 658 659 660 661 662 663 664 665 666

	pr_debug("Searching '%s' variable in context.\n",
		 pf->pvar->var);
	/* Search child die for local variables and parameters. */
	if (!die_find_variable(sp_die, pf->pvar->var, &vr_die)) {
		pr_warning("Failed to find '%s' in this function.\n",
			   pf->pvar->var);
		return -ENOENT;
	}
	return convert_variable(&vr_die, pf);
667 668 669
}

/* Show a probe point to output buffer */
670
static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
671
{
672
	struct kprobe_trace_event *tev;
673 674
	Dwarf_Addr eaddr;
	Dwarf_Die die_mem;
675
	const char *name;
676
	int ret, i;
677 678
	Dwarf_Attribute fb_attr;
	size_t nops;
679

680 681 682 683
	if (pf->ntevs == MAX_PROBES) {
		pr_warning("Too many( > %d) probe point found.\n", MAX_PROBES);
		return -ERANGE;
	}
684 685
	tev = &pf->tevs[pf->ntevs++];

686 687
	/* If no real subprogram, find a real one */
	if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
688
		sp_die = die_find_real_subprogram(&pf->cu_die,
689
						 pf->addr, &die_mem);
690 691 692 693 694
		if (!sp_die) {
			pr_warning("Failed to find probe point in any "
				   "functions.\n");
			return -ENOENT;
		}
695 696
	}

697
	/* Copy the name of probe point */
698 699
	name = dwarf_diename(sp_die);
	if (name) {
700 701 702 703 704
		if (dwarf_entrypc(sp_die, &eaddr) != 0) {
			pr_warning("Failed to get entry pc of %s\n",
				   dwarf_diename(sp_die));
			return -ENOENT;
		}
705 706 707
		tev->point.symbol = strdup(name);
		if (tev->point.symbol == NULL)
			return -ENOMEM;
708 709
		tev->point.offset = (unsigned long)(pf->addr - eaddr);
	} else
710
		/* This function has no name. */
711 712 713 714
		tev->point.offset = (unsigned long)pf->addr;

	pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
		 tev->point.offset);
715

716 717
	/* Get the frame base attribute/ops */
	dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
718
	ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
719
	if (ret <= 0 || nops == 0) {
720
		pf->fb_ops = NULL;
721 722 723
	} else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
		   pf->cfi != NULL) {
		Dwarf_Frame *frame;
724 725 726 727 728 729
		if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
		    dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
			pr_warning("Failed to get CFA on 0x%jx\n",
				   (uintmax_t)pf->addr);
			return -ENOENT;
		}
730
	}
731

732
	/* Find each argument */
733
	tev->nargs = pf->pev->nargs;
734 735 736
	tev->args = zalloc(sizeof(struct kprobe_trace_arg) * tev->nargs);
	if (tev->args == NULL)
		return -ENOMEM;
737 738 739
	for (i = 0; i < pf->pev->nargs; i++) {
		pf->pvar = &pf->pev->args[i];
		pf->tvar = &tev->args[i];
740 741 742
		ret = find_variable(sp_die, pf);
		if (ret != 0)
			return ret;
743
	}
744 745 746

	/* *pf->fb_ops will be cached in libdw. Don't free it. */
	pf->fb_ops = NULL;
747
	return 0;
748 749 750
}

/* Find probe point from its line number */
751
static int find_probe_point_by_line(struct probe_finder *pf)
752
{
753 754 755
	Dwarf_Lines *lines;
	Dwarf_Line *line;
	size_t nlines, i;
756
	Dwarf_Addr addr;
757
	int lineno;
758
	int ret = 0;
759

760 761 762 763
	if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
		pr_warning("No source lines found in this CU.\n");
		return -ENOENT;
	}
764

765
	for (i = 0; i < nlines && ret == 0; i++) {
766
		line = dwarf_onesrcline(lines, i);
767 768
		if (dwarf_lineno(line, &lineno) != 0 ||
		    lineno != pf->lno)
769 770
			continue;

771 772 773
		/* TODO: Get fileno from line, but how? */
		if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
			continue;
774

775 776 777 778
		if (dwarf_lineaddr(line, &addr) != 0) {
			pr_warning("Failed to get the address of the line.\n");
			return -ENOENT;
		}
779 780
		pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
			 (int)i, lineno, (uintmax_t)addr);
781
		pf->addr = addr;
782

783
		ret = convert_probe_point(NULL, pf);
784 785
		/* Continuing, because target line might be inlined. */
	}
786
	return ret;
787 788
}

789 790 791 792 793
/* Find lines which match lazy pattern */
static int find_lazy_match_lines(struct list_head *head,
				 const char *fname, const char *pat)
{
	char *fbuf, *p1, *p2;
794
	int fd, ret, line, nlines = 0;
795 796 797
	struct stat st;

	fd = open(fname, O_RDONLY);
798 799 800 801 802 803 804 805 806 807 808
	if (fd < 0) {
		pr_warning("Failed to open %s: %s\n", fname, strerror(-fd));
		return fd;
	}

	ret = fstat(fd, &st);
	if (ret < 0) {
		pr_warning("Failed to get the size of %s: %s\n",
			   fname, strerror(errno));
		return ret;
	}
809
	fbuf = xmalloc(st.st_size + 2);
810 811 812 813 814
	ret = read(fd, fbuf, st.st_size);
	if (ret < 0) {
		pr_warning("Failed to read %s: %s\n", fname, strerror(errno));
		return ret;
	}
815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833
	close(fd);
	fbuf[st.st_size] = '\n';	/* Dummy line */
	fbuf[st.st_size + 1] = '\0';
	p1 = fbuf;
	line = 1;
	while ((p2 = strchr(p1, '\n')) != NULL) {
		*p2 = '\0';
		if (strlazymatch(p1, pat)) {
			line_list__add_line(head, line);
			nlines++;
		}
		line++;
		p1 = p2 + 1;
	}
	free(fbuf);
	return nlines;
}

/* Find probe points from lazy pattern  */
834
static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
835 836 837 838 839 840 841
{
	Dwarf_Lines *lines;
	Dwarf_Line *line;
	size_t nlines, i;
	Dwarf_Addr addr;
	Dwarf_Die die_mem;
	int lineno;
842
	int ret = 0;
843 844 845 846

	if (list_empty(&pf->lcache)) {
		/* Matching lazy line pattern */
		ret = find_lazy_match_lines(&pf->lcache, pf->fname,
847
					    pf->pev->point.lazy_line);
848 849 850 851 852
		if (ret == 0) {
			pr_debug("No matched lines found in %s.\n", pf->fname);
			return 0;
		} else if (ret < 0)
			return ret;
853 854
	}

855 856 857 858 859 860
	if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
		pr_warning("No source lines found in this CU.\n");
		return -ENOENT;
	}

	for (i = 0; i < nlines && ret >= 0; i++) {
861 862
		line = dwarf_onesrcline(lines, i);

863 864
		if (dwarf_lineno(line, &lineno) != 0 ||
		    !line_list__has_line(&pf->lcache, lineno))
865 866 867 868 869 870
			continue;

		/* TODO: Get fileno from line, but how? */
		if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
			continue;

871 872 873 874 875
		if (dwarf_lineaddr(line, &addr) != 0) {
			pr_debug("Failed to get the address of line %d.\n",
				 lineno);
			continue;
		}
876 877 878 879 880
		if (sp_die) {
			/* Address filtering 1: does sp_die include addr? */
			if (!dwarf_haspc(sp_die, addr))
				continue;
			/* Address filtering 2: No child include addr? */
881
			if (die_find_inlinefunc(sp_die, addr, &die_mem))
882 883 884 885 886 887 888
				continue;
		}

		pr_debug("Probe line found: line[%d]:%d addr:0x%llx\n",
			 (int)i, lineno, (unsigned long long)addr);
		pf->addr = addr;

889
		ret = convert_probe_point(sp_die, pf);
890 891 892
		/* Continuing, because target line might be inlined. */
	}
	/* TODO: deallocate lines, but how? */
893
	return ret;
894 895
}

896 897 898 899 900 901
/* Callback parameter with return value */
struct dwarf_callback_param {
	void *data;
	int retval;
};

902 903
static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
{
904 905
	struct dwarf_callback_param *param = data;
	struct probe_finder *pf = param->data;
906
	struct perf_probe_point *pp = &pf->pev->point;
907
	Dwarf_Addr addr;
908

909
	if (pp->lazy_line)
910
		param->retval = find_probe_point_lazy(in_die, pf);
911 912
	else {
		/* Get probe address */
913 914 915 916 917 918 919
		if (dwarf_entrypc(in_die, &addr) != 0) {
			pr_warning("Failed to get entry pc of %s.\n",
				   dwarf_diename(in_die));
			param->retval = -ENOENT;
			return DWARF_CB_ABORT;
		}
		pf->addr = addr;
920 921 922 923
		pf->addr += pp->offset;
		pr_debug("found inline addr: 0x%jx\n",
			 (uintmax_t)pf->addr);

924
		param->retval = convert_probe_point(in_die, pf);
925
	}
926 927 928

	return DWARF_CB_OK;
}
929

930
/* Search function from function name */
931
static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
932
{
933 934
	struct dwarf_callback_param *param = data;
	struct probe_finder *pf = param->data;
935
	struct perf_probe_point *pp = &pf->pev->point;
936

937 938 939
	/* Check tag and diename */
	if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
	    die_compare_name(sp_die, pp->function) != 0)
940
		return DWARF_CB_OK;
941

942
	pf->fname = dwarf_decl_file(sp_die);
943 944 945
	if (pp->line) { /* Function relative line */
		dwarf_decl_line(sp_die, &pf->lno);
		pf->lno += pp->line;
946
		param->retval = find_probe_point_by_line(pf);
947 948
	} else if (!dwarf_func_inline(sp_die)) {
		/* Real function */
949
		if (pp->lazy_line)
950
			param->retval = find_probe_point_lazy(sp_die, pf);
951
		else {
952 953 954 955 956 957
			if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
				pr_warning("Failed to get entry pc of %s.\n",
					   dwarf_diename(sp_die));
				param->retval = -ENOENT;
				return DWARF_CB_ABORT;
			}
958 959
			pf->addr += pp->offset;
			/* TODO: Check the address in this function */
960
			param->retval = convert_probe_point(sp_die, pf);
961
		}
962 963 964
	} else {
		struct dwarf_callback_param _param = {.data = (void *)pf,
						      .retval = 0};
965
		/* Inlined function: search instances */
966 967 968 969
		dwarf_func_inline_instances(sp_die, probe_point_inline_cb,
					    &_param);
		param->retval = _param.retval;
	}
970

971
	return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
972 973
}

974
static int find_probe_point_by_func(struct probe_finder *pf)
975
{
976 977 978 979
	struct dwarf_callback_param _param = {.data = (void *)pf,
					      .retval = 0};
	dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
	return _param.retval;
980 981
}

982 983 984
/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */
int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
			     struct kprobe_trace_event **tevs)
985
{
986 987
	struct probe_finder pf = {.pev = pev};
	struct perf_probe_point *pp = &pev->point;
988 989 990 991
	Dwarf_Off off, noff;
	size_t cuhl;
	Dwarf_Die *diep;
	Dwarf *dbg;
992
	int ret = 0;
993

994 995 996
	pf.tevs = zalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES);
	if (pf.tevs == NULL)
		return -ENOMEM;
997 998 999
	*tevs = pf.tevs;
	pf.ntevs = 0;

1000
	dbg = dwarf_begin(fd, DWARF_C_READ);
1001 1002 1003 1004 1005
	if (!dbg) {
		pr_warning("No dwarf info found in the vmlinux - "
			"please rebuild with CONFIG_DEBUG_INFO=y.\n");
		return -EBADF;
	}
1006

1007 1008 1009
	/* Get the call frame information from this dwarf */
	pf.cfi = dwarf_getcfi(dbg);

1010
	off = 0;
1011
	line_list__init(&pf.lcache);
1012
	/* Loop on CUs (Compilation Unit) */
1013 1014
	while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) &&
	       ret >= 0) {
1015
		/* Get the DIE(Debugging Information Entry) of this CU */
1016 1017 1018
		diep = dwarf_offdie(dbg, off + cuhl, &pf.cu_die);
		if (!diep)
			continue;
1019 1020 1021

		/* Check if target file is included. */
		if (pp->file)
1022
			pf.fname = cu_find_realpath(&pf.cu_die, pp->file);
1023
		else
1024
			pf.fname = NULL;
1025

1026
		if (!pp->file || pf.fname) {
1027
			if (pp->function)
1028
				ret = find_probe_point_by_func(&pf);
1029
			else if (pp->lazy_line)
1030
				ret = find_probe_point_lazy(NULL, &pf);
1031 1032
			else {
				pf.lno = pp->line;
1033
				ret = find_probe_point_by_line(&pf);
1034
			}
1035
		}
1036
		off = noff;
1037
	}
1038
	line_list__free(&pf.lcache);
1039
	dwarf_end(dbg);
1040

1041
	return (ret < 0) ? ret : pf.ntevs;
1042 1043
}

1044 1045 1046 1047 1048 1049 1050 1051 1052 1053
/* Reverse search */
int find_perf_probe_point(int fd, unsigned long addr,
			  struct perf_probe_point *ppt)
{
	Dwarf_Die cudie, spdie, indie;
	Dwarf *dbg;
	Dwarf_Line *line;
	Dwarf_Addr laddr, eaddr;
	const char *tmp;
	int lineno, ret = 0;
1054
	bool found = false;
1055 1056 1057

	dbg = dwarf_begin(fd, DWARF_C_READ);
	if (!dbg)
1058
		return -EBADF;
1059 1060

	/* Find cu die */
1061 1062 1063 1064
	if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) {
		ret = -EINVAL;
		goto end;
	}
1065 1066 1067 1068

	/* Find a corresponding line */
	line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr);
	if (line) {
1069 1070 1071
		if (dwarf_lineaddr(line, &laddr) == 0 &&
		    (Dwarf_Addr)addr == laddr &&
		    dwarf_lineno(line, &lineno) == 0) {
1072
			tmp = dwarf_linesrc(line, NULL, NULL);
1073 1074
			if (tmp) {
				ppt->line = lineno;
1075 1076 1077 1078 1079
				ppt->file = strdup(tmp);
				if (ppt->file == NULL) {
					ret = -ENOMEM;
					goto end;
				}
1080 1081
				found = true;
			}
1082 1083 1084 1085 1086 1087
		}
	}

	/* Find a corresponding function */
	if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) {
		tmp = dwarf_diename(&spdie);
1088
		if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0)
1089 1090
			goto end;

1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
		if (ppt->line) {
			if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
						&indie)) {
				/* addr in an inline function */
				tmp = dwarf_diename(&indie);
				if (!tmp)
					goto end;
				ret = dwarf_decl_line(&indie, &lineno);
			} else {
				if (eaddr == addr) {	/* Function entry */
					lineno = ppt->line;
					ret = 0;
				} else
					ret = dwarf_decl_line(&spdie, &lineno);
			}
			if (ret == 0) {
				/* Make a relative line number */
				ppt->line -= lineno;
				goto found;
			}
1111
		}
1112 1113 1114
		/* We don't have a line number, let's use offset */
		ppt->offset = addr - (unsigned long)eaddr;
found:
1115 1116 1117 1118 1119
		ppt->function = strdup(tmp);
		if (ppt->function == NULL) {
			ret = -ENOMEM;
			goto end;
		}
1120
		found = true;
1121 1122 1123 1124
	}

end:
	dwarf_end(dbg);
1125 1126
	if (ret >= 0)
		ret = found ? 1 : 0;
1127 1128 1129
	return ret;
}

1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168
/* Add a line and store the src path */
static int line_range_add_line(const char *src, unsigned int lineno,
			       struct line_range *lr)
{
	/* Copy real path */
	if (!lr->path) {
		lr->path = strdup(src);
		if (lr->path == NULL)
			return -ENOMEM;
	}
	return line_list__add_line(&lr->line_list, lineno);
}

/* Search function declaration lines */
static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data)
{
	struct dwarf_callback_param *param = data;
	struct line_finder *lf = param->data;
	const char *src;
	int lineno;

	src = dwarf_decl_file(sp_die);
	if (src && strtailcmp(src, lf->fname) != 0)
		return DWARF_CB_OK;

	if (dwarf_decl_line(sp_die, &lineno) != 0 ||
	    (lf->lno_s > lineno || lf->lno_e < lineno))
		return DWARF_CB_OK;

	param->retval = line_range_add_line(src, lineno, lf->lr);
	return DWARF_CB_OK;
}

static int find_line_range_func_decl_lines(struct line_finder *lf)
{
	struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
	dwarf_getfuncs(&lf->cu_die, line_range_funcdecl_cb, &param, 0);
	return param.retval;
}
1169

1170
/* Find line range from its line number */
1171
static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1172
{
1173 1174 1175
	Dwarf_Lines *lines;
	Dwarf_Line *line;
	size_t nlines, i;
1176
	Dwarf_Addr addr;
1177
	int lineno, ret = 0;
1178
	const char *src;
1179
	Dwarf_Die die_mem;
1180

1181
	line_list__init(&lf->lr->line_list);
1182 1183 1184 1185
	if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
		pr_warning("No source lines found in this CU.\n");
		return -ENOENT;
	}
1186

1187
	/* Search probable lines on lines list */
1188 1189
	for (i = 0; i < nlines; i++) {
		line = dwarf_onesrcline(lines, i);
1190 1191
		if (dwarf_lineno(line, &lineno) != 0 ||
		    (lf->lno_s > lineno || lf->lno_e < lineno))
1192 1193
			continue;

1194 1195
		if (sp_die) {
			/* Address filtering 1: does sp_die include addr? */
1196 1197
			if (dwarf_lineaddr(line, &addr) != 0 ||
			    !dwarf_haspc(sp_die, addr))
1198 1199 1200
				continue;

			/* Address filtering 2: No child include addr? */
1201
			if (die_find_inlinefunc(sp_die, addr, &die_mem))
1202 1203 1204
				continue;
		}

1205 1206 1207
		/* TODO: Get fileno from line, but how? */
		src = dwarf_linesrc(line, NULL, NULL);
		if (strtailcmp(src, lf->fname) != 0)
1208 1209
			continue;

1210 1211 1212
		ret = line_range_add_line(src, lineno, lf->lr);
		if (ret < 0)
			return ret;
1213
	}
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226

	/*
	 * Dwarf lines doesn't include function declarations. We have to
	 * check functions list or given function.
	 */
	if (sp_die) {
		src = dwarf_decl_file(sp_die);
		if (src && dwarf_decl_line(sp_die, &lineno) == 0 &&
		    (lf->lno_s <= lineno && lf->lno_e >= lineno))
			ret = line_range_add_line(src, lineno, lf->lr);
	} else
		ret = find_line_range_func_decl_lines(lf);

1227
	/* Update status */
1228 1229 1230 1231 1232
	if (ret >= 0)
		if (!list_empty(&lf->lr->line_list))
			ret = lf->found = 1;
		else
			ret = 0;	/* Lines are not found */
1233 1234 1235 1236
	else {
		free(lf->lr->path);
		lf->lr->path = NULL;
	}
1237
	return ret;
1238 1239
}

1240 1241
static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
{
1242 1243 1244
	struct dwarf_callback_param *param = data;

	param->retval = find_line_range_by_line(in_die, param->data);
1245 1246 1247
	return DWARF_CB_ABORT;	/* No need to find other instances */
}

1248
/* Search function from function name */
1249
static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1250
{
1251 1252
	struct dwarf_callback_param *param = data;
	struct line_finder *lf = param->data;
1253 1254
	struct line_range *lr = lf->lr;

1255 1256 1257 1258
	if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
	    die_compare_name(sp_die, lr->function) == 0) {
		lf->fname = dwarf_decl_file(sp_die);
		dwarf_decl_line(sp_die, &lr->offset);
1259
		pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
1260
		lf->lno_s = lr->offset + lr->start;
1261 1262 1263 1264
		if (lf->lno_s < 0)	/* Overflow */
			lf->lno_s = INT_MAX;
		lf->lno_e = lr->offset + lr->end;
		if (lf->lno_e < 0)	/* Overflow */
1265
			lf->lno_e = INT_MAX;
1266
		pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
1267 1268
		lr->start = lf->lno_s;
		lr->end = lf->lno_e;
1269 1270 1271 1272
		if (dwarf_func_inline(sp_die)) {
			struct dwarf_callback_param _param;
			_param.data = (void *)lf;
			_param.retval = 0;
1273
			dwarf_func_inline_instances(sp_die,
1274 1275 1276 1277 1278 1279
						    line_range_inline_cb,
						    &_param);
			param->retval = _param.retval;
		} else
			param->retval = find_line_range_by_line(sp_die, lf);
		return DWARF_CB_ABORT;
1280
	}
1281
	return DWARF_CB_OK;
1282 1283
}

1284
static int find_line_range_by_func(struct line_finder *lf)
1285
{
1286 1287 1288
	struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
	dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
	return param.retval;
1289 1290 1291 1292
}

int find_line_range(int fd, struct line_range *lr)
{
1293
	struct line_finder lf = {.lr = lr, .found = 0};
1294
	int ret = 0;
1295 1296 1297 1298 1299 1300
	Dwarf_Off off = 0, noff;
	size_t cuhl;
	Dwarf_Die *diep;
	Dwarf *dbg;

	dbg = dwarf_begin(fd, DWARF_C_READ);
1301 1302 1303 1304 1305
	if (!dbg) {
		pr_warning("No dwarf info found in the vmlinux - "
			"please rebuild with CONFIG_DEBUG_INFO=y.\n");
		return -EBADF;
	}
1306

1307
	/* Loop on CUs (Compilation Unit) */
1308 1309
	while (!lf.found && ret >= 0) {
		if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0)
1310 1311 1312
			break;

		/* Get the DIE(Debugging Information Entry) of this CU */
1313 1314 1315
		diep = dwarf_offdie(dbg, off + cuhl, &lf.cu_die);
		if (!diep)
			continue;
1316 1317 1318

		/* Check if target file is included. */
		if (lr->file)
1319
			lf.fname = cu_find_realpath(&lf.cu_die, lr->file);
1320
		else
1321
			lf.fname = 0;
1322

1323
		if (!lr->file || lf.fname) {
1324
			if (lr->function)
1325
				ret = find_line_range_by_func(&lf);
1326 1327
			else {
				lf.lno_s = lr->start;
1328
				lf.lno_e = lr->end;
1329
				ret = find_line_range_by_line(NULL, &lf);
1330 1331
			}
		}
1332
		off = noff;
1333
	}
1334 1335
	pr_debug("path: %lx\n", (unsigned long)lr->path);
	dwarf_end(dbg);
1336 1337

	return (ret < 0) ? ret : lf.found;
1338 1339
}