diff options
Diffstat (limited to 'tools/perf/util/probe-finder.c')
| -rw-r--r-- | tools/perf/util/probe-finder.c | 49 | 
1 files changed, 33 insertions, 16 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 371476cb8ddc..c09e0a9fdf4c 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -1327,8 +1327,8 @@ int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,  				struct perf_probe_point *ppt)  {  	Dwarf_Die cudie, spdie, indie; -	Dwarf_Addr _addr, baseaddr; -	const char *fname = NULL, *func = NULL, *tmp; +	Dwarf_Addr _addr = 0, baseaddr = 0; +	const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;  	int baseline = 0, lineno = 0, ret = 0;  	/* Adjust address with bias */ @@ -1349,27 +1349,36 @@ int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,  	/* Find a corresponding function (name, baseline and baseaddr) */  	if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) {  		/* Get function entry information */ -		tmp = dwarf_diename(&spdie); -		if (!tmp || +		func = basefunc = dwarf_diename(&spdie); +		if (!func ||  		    dwarf_entrypc(&spdie, &baseaddr) != 0 || -		    dwarf_decl_line(&spdie, &baseline) != 0) +		    dwarf_decl_line(&spdie, &baseline) != 0) { +			lineno = 0;  			goto post; -		func = tmp; +		} -		if (addr == (unsigned long)baseaddr) +		if (addr == (unsigned long)baseaddr) {  			/* Function entry - Relative line number is 0 */  			lineno = baseline; -		else if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr, -					     &indie)) { +			fname = dwarf_decl_file(&spdie); +			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 */  			if (dwarf_entrypc(&indie, &_addr) == 0 && -			    _addr == addr) +			    _addr == addr) {  				/*  				 * addr is at an inline function entry.  				 * In this case, lineno should be the call-site -				 * line number. +				 * line number. (overwrite lineinfo)  				 */  				lineno = die_get_call_lineno(&indie); -			else { +				fname = die_get_call_file(&indie); +				break; +			} else {  				/*  				 * addr is in an inline function body.  				 * Since lineno points one of the lines @@ -1377,19 +1386,27 @@ int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,  				 * be the entry line of the inline function.  				 */  				tmp = dwarf_diename(&indie); -				if (tmp && -				    dwarf_decl_line(&spdie, &baseline) == 0) -					func = tmp; +				if (!tmp || +				    dwarf_decl_line(&indie, &baseline) != 0) +					break; +				func = tmp; +				spdie = indie;  			}  		} +		/* Verify the lineno and baseline are in a same file */ +		tmp = dwarf_decl_file(&spdie); +		if (!tmp || strcmp(tmp, fname) != 0) +			lineno = 0;  	}  post:  	/* Make a relative line number or an offset */  	if (lineno)  		ppt->line = lineno - baseline; -	else if (func) +	else if (basefunc) {  		ppt->offset = addr - (unsigned long)baseaddr; +		func = basefunc; +	}  	/* Duplicate strings */  	if (func) {  | 
