aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2011-03-30 05:26:05 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-04-05 14:38:12 -0400
commit1d46ea2a6a405196435ffcc2adb3ef5402a30b3a (patch)
tree12343b40748ed5928ccfe8421c75b4f9ae1497dd /tools
parent1d878083c253fb2e2471b39e825447aca66fc05c (diff)
perf probe: Fix listing incorrect line number with inline function
Fix a bug showing incorrect line number when a probe is put on the head of an inline function. This patch updates find_perf_probe_point() and introduces new rules to get correct line number. - If debuginfo doesn't have a correct file name, we shouldn't return line number too, because, without file name, line number is meaningless. - If the address is in a function, it stores the function name and the offset from the function entry. - If the address is on a line, it tries to get the relative line number from the function entry line, except for the address is same as the entry address of the function (in this case, the relative line number should be 0). - If the address is in an inline function entry (call-site), it uses the inline function call line number as the line on which the address is. - If the address is in an inline function body, it stores the inline function name and offset from the inline function call site instead of the (non-inlined) function. Cc: 2nddept-manager@sdl.hitachi.co.jp Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Lin Ming <ming.m.lin@intel.com> Cc: Peter Zijlstra <peterz@infradead.org> LKML-Reference: <20110330092605.2132.11629.stgit@ltc236.sdl.hitachi.co.jp> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/probe-finder.c134
1 files changed, 81 insertions, 53 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 689ab462a188..b7c85ce466a1 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -273,6 +273,25 @@ static const char *cu_get_comp_dir(Dwarf_Die *cu_die)
273 return dwarf_formstring(&attr); 273 return dwarf_formstring(&attr);
274} 274}
275 275
276/* Get a line number and file name for given address */
277static int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
278 const char **fname, int *lineno)
279{
280 Dwarf_Line *line;
281 Dwarf_Addr laddr;
282
283 line = dwarf_getsrc_die(cudie, (Dwarf_Addr)addr);
284 if (line && dwarf_lineaddr(line, &laddr) == 0 &&
285 addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) {
286 *fname = dwarf_linesrc(line, NULL, NULL);
287 if (!*fname)
288 /* line number is useless without filename */
289 *lineno = 0;
290 }
291
292 return *lineno ?: -ENOENT;
293}
294
276/* Compare diename and tname */ 295/* Compare diename and tname */
277static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) 296static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
278{ 297{
@@ -1704,11 +1723,9 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1704 Dwarf_Die cudie, spdie, indie; 1723 Dwarf_Die cudie, spdie, indie;
1705 Dwarf *dbg = NULL; 1724 Dwarf *dbg = NULL;
1706 Dwfl *dwfl = NULL; 1725 Dwfl *dwfl = NULL;
1707 Dwarf_Line *line; 1726 Dwarf_Addr _addr, baseaddr, bias = 0;
1708 Dwarf_Addr laddr, eaddr, bias = 0; 1727 const char *fname = NULL, *func = NULL, *tmp;
1709 const char *tmp; 1728 int baseline = 0, lineno = 0, ret = 0;
1710 int lineno, ret = 0;
1711 bool found = false;
1712 1729
1713 /* Open the live linux kernel */ 1730 /* Open the live linux kernel */
1714 dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias); 1731 dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias);
@@ -1729,68 +1746,79 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1729 goto end; 1746 goto end;
1730 } 1747 }
1731 1748
1732 /* Find a corresponding line */ 1749 /* Find a corresponding line (filename and lineno) */
1733 line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr); 1750 cu_find_lineinfo(&cudie, addr, &fname, &lineno);
1734 if (line) { 1751 /* Don't care whether it failed or not */
1735 if (dwarf_lineaddr(line, &laddr) == 0 &&
1736 (Dwarf_Addr)addr == laddr &&
1737 dwarf_lineno(line, &lineno) == 0) {
1738 tmp = dwarf_linesrc(line, NULL, NULL);
1739 if (tmp) {
1740 ppt->line = lineno;
1741 ppt->file = strdup(tmp);
1742 if (ppt->file == NULL) {
1743 ret = -ENOMEM;
1744 goto end;
1745 }
1746 found = true;
1747 }
1748 }
1749 }
1750 1752
1751 /* Find a corresponding function */ 1753 /* Find a corresponding function (name, baseline and baseaddr) */
1752 if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) { 1754 if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) {
1755 /* Get function entry information */
1753 tmp = dwarf_diename(&spdie); 1756 tmp = dwarf_diename(&spdie);
1754 if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0) 1757 if (!tmp ||
1755 goto end; 1758 dwarf_entrypc(&spdie, &baseaddr) != 0 ||
1756 1759 dwarf_decl_line(&spdie, &baseline) != 0)
1757 if (ppt->line) { 1760 goto post;
1758 if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr, 1761 func = tmp;
1759 &indie)) { 1762
1760 /* addr in an inline function */ 1763 if (addr == (unsigned long)baseaddr)
1764 /* Function entry - Relative line number is 0 */
1765 lineno = baseline;
1766 else if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
1767 &indie)) {
1768 if (dwarf_entrypc(&indie, &_addr) == 0 &&
1769 _addr == addr)
1770 /*
1771 * addr is at an inline function entry.
1772 * In this case, lineno should be the call-site
1773 * line number.
1774 */
1775 lineno = die_get_call_lineno(&indie);
1776 else {
1777 /*
1778 * addr is in an inline function body.
1779 * Since lineno points one of the lines
1780 * of the inline function, baseline should
1781 * be the entry line of the inline function.
1782 */
1761 tmp = dwarf_diename(&indie); 1783 tmp = dwarf_diename(&indie);
1762 if (!tmp) 1784 if (tmp &&
1763 goto end; 1785 dwarf_decl_line(&spdie, &baseline) == 0)
1764 ret = dwarf_decl_line(&indie, &lineno); 1786 func = tmp;
1765 } else {
1766 if (eaddr == addr) { /* Function entry */
1767 lineno = ppt->line;
1768 ret = 0;
1769 } else
1770 ret = dwarf_decl_line(&spdie, &lineno);
1771 }
1772 if (ret == 0) {
1773 /* Make a relative line number */
1774 ppt->line -= lineno;
1775 goto found;
1776 } 1787 }
1777 } 1788 }
1778 /* We don't have a line number, let's use offset */ 1789 }
1779 ppt->offset = addr - (unsigned long)eaddr; 1790
1780found: 1791post:
1781 ppt->function = strdup(tmp); 1792 /* Make a relative line number or an offset */
1793 if (lineno)
1794 ppt->line = lineno - baseline;
1795 else if (func)
1796 ppt->offset = addr - (unsigned long)baseaddr;
1797
1798 /* Duplicate strings */
1799 if (func) {
1800 ppt->function = strdup(func);
1782 if (ppt->function == NULL) { 1801 if (ppt->function == NULL) {
1783 ret = -ENOMEM; 1802 ret = -ENOMEM;
1784 goto end; 1803 goto end;
1785 } 1804 }
1786 found = true;
1787 } 1805 }
1788 1806 if (fname) {
1807 ppt->file = strdup(fname);
1808 if (ppt->file == NULL) {
1809 if (ppt->function) {
1810 free(ppt->function);
1811 ppt->function = NULL;
1812 }
1813 ret = -ENOMEM;
1814 goto end;
1815 }
1816 }
1789end: 1817end:
1790 if (dwfl) 1818 if (dwfl)
1791 dwfl_end(dwfl); 1819 dwfl_end(dwfl);
1792 if (ret >= 0) 1820 if (ret == 0 && (fname || func))
1793 ret = found ? 1 : 0; 1821 ret = 1; /* Found a point */
1794 return ret; 1822 return ret;
1795} 1823}
1796 1824