lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20180514041940.96126-6-automatic+kernel@freyther.de>
Date:   Mon, 14 May 2018 12:19:39 +0800
From:   Holger Freyther <automatic+kernel@...yther.de>
To:     linux-kernel@...r.kernel.org
Cc:     Holger Hans Peter Freyther <holgar+kernel@...gle.com>
Subject: [RFC 5/6] perf probe: Make listing of variables work for C++ functions

From: Holger Hans Peter Freyther <holgar+kernel@...gle.com>

Update call sites with die_match_name to call matches_demangled as well.
This requires to pass the struct debuginfo/struct dso to the callbacks
and modifies the closure/void *data parameter. For most functions this
will change the parameter from struct probe_finder to the generic struct
dwarf_callback_param.

$ ./perf probe -x ./foo -V "std::vector<int, std::allocator<int> >::at"
Available variables at std::vector<int, std::allocator<int> >::at
        @<at+0>
                size_type       __n
                vector<int, std::allocator<int> >*      this

Signed-off-by: Holger Hans Peter Freyther <holgar+kernel@...gle.com>
---
 tools/perf/util/probe-finder.c | 88 +++++++++++++++++++++++++++---------------
 1 file changed, 56 insertions(+), 32 deletions(-)

diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index c73dccc..4ba4b18 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -760,6 +760,7 @@ struct find_scope_param {
 	int line;
 	int diff;
 	Dwarf_Die *die_mem;
+	struct debuginfo *dbg;
 	bool found;
 };
 
@@ -777,7 +778,8 @@ static int find_best_scope_cb(Dwarf_Die *fn_die, void *data)
 	}
 	/* If the function name is given, that's what user expects */
 	if (fsp->function) {
-		if (die_match_name(fn_die, fsp->function)) {
+		if (die_match_name(fn_die, fsp->function) ||
+			matches_demangled(fsp->dbg, fn_die, fsp->function)) {
 			memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
 			fsp->found = true;
 			return 1;
@@ -795,8 +797,16 @@ static int find_best_scope_cb(Dwarf_Die *fn_die, void *data)
 	return 0;
 }
 
+/* Callback parameter with return value for libdw */
+struct dwarf_callback_param {
+	void *data;
+	int retval;
+	struct debuginfo *dbg;
+};
+
 /* Find an appropriate scope fits to given conditions */
-static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem)
+static Dwarf_Die *find_best_scope(struct debuginfo *dbg,
+				  struct probe_finder *pf, Dwarf_Die *die_mem)
 {
 	struct find_scope_param fsp = {
 		.function = pf->pev->point.function,
@@ -804,6 +814,7 @@ static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem)
 		.line = pf->lno,
 		.diff = INT_MAX,
 		.die_mem = die_mem,
+		.dbg = dbg,
 		.found = false,
 	};
 
@@ -815,7 +826,8 @@ static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem)
 static int probe_point_line_walker(const char *fname, int lineno,
 				   Dwarf_Addr addr, void *data)
 {
-	struct probe_finder *pf = data;
+	struct dwarf_callback_param *param = data;
+	struct probe_finder *pf = param->data;
 	Dwarf_Die *sc_die, die_mem;
 	int ret;
 
@@ -823,7 +835,7 @@ static int probe_point_line_walker(const char *fname, int lineno,
 		return 0;
 
 	pf->addr = addr;
-	sc_die = find_best_scope(pf, &die_mem);
+	sc_die = find_best_scope(param->dbg, pf, &die_mem);
 	if (!sc_die) {
 		pr_warning("Failed to find scope of probe point.\n");
 		return -ENOENT;
@@ -836,9 +848,12 @@ static int probe_point_line_walker(const char *fname, int lineno,
 }
 
 /* Find probe point from its line number */
-static int find_probe_point_by_line(struct probe_finder *pf)
+static int find_probe_point_by_line(struct debuginfo *dbg,
+				    struct probe_finder *pf)
 {
-	return die_walk_lines(&pf->cu_die, probe_point_line_walker, pf);
+	struct dwarf_callback_param param = {
+		.data = (void *)pf, .dbg = dbg, .retval = 0};
+	return die_walk_lines(&pf->cu_die, probe_point_line_walker, &param);
 }
 
 /* Find lines which match lazy pattern */
@@ -884,7 +899,8 @@ static int find_lazy_match_lines(struct intlist *list,
 static int probe_point_lazy_walker(const char *fname, int lineno,
 				   Dwarf_Addr addr, void *data)
 {
-	struct probe_finder *pf = data;
+	struct dwarf_callback_param *param = data;
+	struct probe_finder *pf = param->data;
 	Dwarf_Die *sc_die, die_mem;
 	int ret;
 
@@ -896,7 +912,7 @@ static int probe_point_lazy_walker(const char *fname, int lineno,
 		 lineno, (unsigned long long)addr);
 	pf->addr = addr;
 	pf->lno = lineno;
-	sc_die = find_best_scope(pf, &die_mem);
+	sc_die = find_best_scope(param->dbg, pf, &die_mem);
 	if (!sc_die) {
 		pr_warning("Failed to find scope of probe point.\n");
 		return -ENOENT;
@@ -912,8 +928,10 @@ static int probe_point_lazy_walker(const char *fname, int lineno,
 }
 
 /* Find probe points from lazy pattern  */
-static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
+static int find_probe_point_lazy(Dwarf_Die *sp_die,
+				 struct dwarf_callback_param *param)
 {
+	struct probe_finder *pf = param->data;
 	int ret = 0;
 	char *fpath;
 
@@ -935,7 +953,7 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
 			return ret;
 	}
 
-	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
+	return die_walk_lines(sp_die, probe_point_lazy_walker, param);
 }
 
 static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
@@ -972,13 +990,14 @@ static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
 
 static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
 {
-	struct probe_finder *pf = data;
+	struct dwarf_callback_param *param = data;
+	struct probe_finder *pf = param->data;
 	struct perf_probe_point *pp = &pf->pev->point;
 	Dwarf_Addr addr;
 	int ret;
 
 	if (pp->lazy_line)
-		ret = find_probe_point_lazy(in_die, pf);
+		ret = find_probe_point_lazy(in_die, param);
 	else {
 		/* Get probe address */
 		if (dwarf_entrypc(in_die, &addr) != 0) {
@@ -1002,13 +1021,6 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
 	return ret;
 }
 
-/* Callback parameter with return value for libdw */
-struct dwarf_callback_param {
-	void *data;
-	int retval;
-	struct debuginfo *dbg;
-};
-
 /* Search function from function name */
 static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
 {
@@ -1018,7 +1030,8 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
 
 	/* Check tag and diename */
 	if (!die_is_func_def(sp_die) ||
-	    !die_match_name(sp_die, pp->function))
+	    (!die_match_name(sp_die, pp->function) &&
+	     !matches_demangled(param->dbg, sp_die, pp->function)))
 		return DWARF_CB_OK;
 
 	/* Check declared file */
@@ -1031,7 +1044,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
 	if (pp->line) { /* Function relative line */
 		dwarf_decl_line(sp_die, &pf->lno);
 		pf->lno += pp->line;
-		param->retval = find_probe_point_by_line(pf);
+		param->retval = find_probe_point_by_line(param->dbg, pf);
 	} else if (die_is_func_instance(sp_die)) {
 		/* Instances always have the entry address */
 		dwarf_entrypc(sp_die, &pf->addr);
@@ -1042,7 +1055,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
 			param->retval = 0;
 		/* Real function */
 		} else if (pp->lazy_line)
-			param->retval = find_probe_point_lazy(sp_die, pf);
+			param->retval = find_probe_point_lazy(sp_die, param);
 		else {
 			skip_prologue(sp_die, pf);
 			pf->addr += pp->offset;
@@ -1052,7 +1065,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
 	} else if (!probe_conf.no_inlines) {
 		/* Inlined function: search instances */
 		param->retval = die_walk_instances(sp_die,
-					probe_point_inline_cb, (void *)pf);
+					probe_point_inline_cb, data);
 		/* This could be a non-existed inline definition */
 		if (param->retval == -ENOENT)
 			param->retval = 0;
@@ -1067,9 +1080,10 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
 	return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
 }
 
-static int find_probe_point_by_func(struct probe_finder *pf)
+static int find_probe_point_by_func(struct debuginfo *dbg,
+				    struct probe_finder *pf)
 {
-	struct dwarf_callback_param _param = {.data = (void *)pf,
+	struct dwarf_callback_param _param = {.data = (void *)pf, .dbg = dbg,
 					      .retval = 0};
 	dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
 	return _param.retval;
@@ -1080,6 +1094,7 @@ struct pubname_callback_param {
 	char *file;
 	Dwarf_Die *cu_die;
 	Dwarf_Die *sp_die;
+	struct debuginfo *dbg;
 	int found;
 };
 
@@ -1091,7 +1106,9 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
 		if (dwarf_tag(param->sp_die) != DW_TAG_subprogram)
 			return DWARF_CB_OK;
 
-		if (die_match_name(param->sp_die, param->function)) {
+		if (die_match_name(param->sp_die, param->function) ||
+			matches_demangled(param->dbg, param->sp_die,
+					  param->function)) {
 			if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die))
 				return DWARF_CB_OK;
 
@@ -1128,10 +1145,12 @@ static int debuginfo__find_probe_location(struct debuginfo *dbg,
 			.file	  = pp->file,
 			.cu_die	  = &pf->cu_die,
 			.sp_die	  = &pf->sp_die,
+			.dbg      = dbg,
 			.found	  = 0,
 		};
 		struct dwarf_callback_param probe_param = {
 			.data = pf,
+			.dbg  = dbg,
 		};
 
 		dwarf_getpubnames(dbg->dbg, pubname_search_cb,
@@ -1158,12 +1177,17 @@ static int debuginfo__find_probe_location(struct debuginfo *dbg,
 
 		if (!pp->file || pf->fname) {
 			if (pp->function)
-				ret = find_probe_point_by_func(pf);
-			else if (pp->lazy_line)
-				ret = find_probe_point_lazy(&pf->cu_die, pf);
-			else {
+				ret = find_probe_point_by_func(dbg, pf);
+			else if (pp->lazy_line) {
+				struct dwarf_callback_param probe_param = {
+					.data = pf,
+					.dbg  = dbg,
+				};
+				ret = find_probe_point_lazy(&pf->cu_die,
+							    &probe_param);
+			} else {
 				pf->lno = pp->line;
-				ret = find_probe_point_by_line(pf);
+				ret = find_probe_point_by_line(dbg, pf);
 			}
 			if (ret < 0)
 				break;
@@ -1798,7 +1822,7 @@ int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr)
 	/* Fastpath: lookup by function name from .debug_pubnames section */
 	if (lr->function) {
 		struct pubname_callback_param pubname_param = {
-			.function = lr->function, .file = lr->file,
+			.function = lr->function, .file = lr->file, .dbg = dbg,
 			.cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0};
 		struct dwarf_callback_param line_range_param = {
 			.data = (void *)&lf, .retval = 0, .dbg = dbg};
-- 
2.7.4

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ