perf probe: Fix add event failure when running 32-bit perf in a 64-bit kernel

The "address" member of "struct probe_trace_point" uses long data type.
If kernel is 64-bit and perf program is 32-bit, size of "address"
variable is 32 bits.

As a result, upper 32 bits of address read from kernel are truncated, an
error occurs during address comparison in kprobe_warn_out_range().

Before:

# perf probe -a schedule
schedule is out of .text, skip it.
Error: Failed to add events.

Solution:
Change data type of "address" variable to u64 and change corresponding
address printing and value assignment.

After:

# perf.new.new probe -a schedule
Added new event:
probe:schedule (on schedule)

You can now use it in all perf tools, such as:

perf record -e probe:schedule -aR sleep 1

# perf probe -l
probe:schedule (on schedule@kernel/sched/core.c)
# perf record -e probe:schedule -aR sleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.156 MB perf.data (1366 samples) ]
# perf report --stdio
# To display the perf.data header info, please use --header/--header-only options.
#
#
# Total Lost Samples: 0
#
# Samples: 1K of event 'probe:schedule'
# Event count (approx.): 1366
#
# Overhead Command Shared Object Symbol
# ........ ............... ................. ............
#
6.22% migration/0 [kernel.kallsyms] [k] schedule
6.22% migration/1 [kernel.kallsyms] [k] schedule
6.22% migration/2 [kernel.kallsyms] [k] schedule
6.22% migration/3 [kernel.kallsyms] [k] schedule
6.15% migration/10 [kernel.kallsyms] [k] schedule
6.15% migration/11 [kernel.kallsyms] [k] schedule
6.15% migration/12 [kernel.kallsyms] [k] schedule
6.15% migration/13 [kernel.kallsyms] [k] schedule
6.15% migration/14 [kernel.kallsyms] [k] schedule
6.15% migration/15 [kernel.kallsyms] [k] schedule
6.15% migration/4 [kernel.kallsyms] [k] schedule
6.15% migration/5 [kernel.kallsyms] [k] schedule
6.15% migration/6 [kernel.kallsyms] [k] schedule
6.15% migration/7 [kernel.kallsyms] [k] schedule
6.15% migration/8 [kernel.kallsyms] [k] schedule
6.15% migration/9 [kernel.kallsyms] [k] schedule
0.22% rcu_sched [kernel.kallsyms] [k] schedule
...
#
# (Cannot load tips.txt file, please install perf!)
#

Signed-off-by: Yang Jihong <yangjihong1@huawei.com>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Frank Ch. Eigler <fche@redhat.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Jianlin Lv <jianlin.lv@arm.com>
Cc: Jin Yao <yao.jin@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Li Huafei <lihuafei1@huawei.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Link: http://lore.kernel.org/lkml/20210715063723.11926-1-yangjihong1@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by Yang Jihong and committed by Arnaldo Carvalho de Melo 22a66551 d4b3eedc

+4 -4
tools/perf/util/dwarf-aux.c
··· 113 113 * 114 114 * Find a line number and file name for @addr in @cu_die. 115 115 */ 116 - int cu_find_lineinfo(Dwarf_Die *cu_die, unsigned long addr, 117 - const char **fname, int *lineno) 116 + int cu_find_lineinfo(Dwarf_Die *cu_die, Dwarf_Addr addr, 117 + const char **fname, int *lineno) 118 118 { 119 119 Dwarf_Line *line; 120 120 Dwarf_Die die_mem; 121 121 Dwarf_Addr faddr; 122 122 123 - if (die_find_realfunc(cu_die, (Dwarf_Addr)addr, &die_mem) 123 + if (die_find_realfunc(cu_die, addr, &die_mem) 124 124 && die_entrypc(&die_mem, &faddr) == 0 && 125 125 faddr == addr) { 126 126 *fname = dwarf_decl_file(&die_mem); ··· 128 128 goto out; 129 129 } 130 130 131 - line = cu_getsrc_die(cu_die, (Dwarf_Addr)addr); 131 + line = cu_getsrc_die(cu_die, addr); 132 132 if (line && dwarf_lineno(line, lineno) == 0) { 133 133 *fname = dwarf_linesrc(line, NULL, NULL); 134 134 if (!*fname)
+1 -1
tools/perf/util/dwarf-aux.h
··· 19 19 const char *cu_get_comp_dir(Dwarf_Die *cu_die); 20 20 21 21 /* Get a line number and file name for given address */ 22 - int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr, 22 + int cu_find_lineinfo(Dwarf_Die *cudie, Dwarf_Addr addr, 23 23 const char **fname, int *lineno); 24 24 25 25 /* Walk on functions at given address */
+23 -26
tools/perf/util/probe-event.c
··· 239 239 clear_probe_trace_event(tevs + i); 240 240 } 241 241 242 - static bool kprobe_blacklist__listed(unsigned long address); 243 - static bool kprobe_warn_out_range(const char *symbol, unsigned long address) 242 + static bool kprobe_blacklist__listed(u64 address); 243 + static bool kprobe_warn_out_range(const char *symbol, u64 address) 244 244 { 245 245 struct map *map; 246 246 bool ret = false; ··· 400 400 pr_debug("Symbol %s address found : %" PRIx64 "\n", 401 401 pp->function, address); 402 402 403 - ret = debuginfo__find_probe_point(dinfo, (unsigned long)address, 404 - result); 403 + ret = debuginfo__find_probe_point(dinfo, address, result); 405 404 if (ret <= 0) 406 405 ret = (!ret) ? -ENOENT : ret; 407 406 else { ··· 588 589 } 589 590 590 591 591 - static int get_text_start_address(const char *exec, unsigned long *address, 592 + static int get_text_start_address(const char *exec, u64 *address, 592 593 struct nsinfo *nsi) 593 594 { 594 595 Elf *elf; ··· 633 634 bool is_kprobe) 634 635 { 635 636 struct debuginfo *dinfo = NULL; 636 - unsigned long stext = 0; 637 + u64 stext = 0; 637 638 u64 addr = tp->address; 638 639 int ret = -ENOENT; 639 640 ··· 661 662 662 663 dinfo = debuginfo_cache__open(tp->module, verbose <= 0); 663 664 if (dinfo) 664 - ret = debuginfo__find_probe_point(dinfo, 665 - (unsigned long)addr, pp); 665 + ret = debuginfo__find_probe_point(dinfo, addr, pp); 666 666 else 667 667 ret = -ENOENT; 668 668 ··· 676 678 677 679 /* Adjust symbol name and address */ 678 680 static int post_process_probe_trace_point(struct probe_trace_point *tp, 679 - struct map *map, unsigned long offs) 681 + struct map *map, u64 offs) 680 682 { 681 683 struct symbol *sym; 682 684 u64 addr = tp->address - offs; ··· 719 721 int ntevs, const char *pathname) 720 722 { 721 723 struct map *map; 722 - unsigned long stext = 0; 724 + u64 stext = 0; 723 725 int i, ret = 0; 724 726 725 727 /* Prepare a map for offline binary */ ··· 745 747 struct nsinfo *nsi) 746 748 { 747 749 int i, ret = 0; 748 - unsigned long stext = 0; 750 + u64 stext = 0; 749 751 750 752 if (!exec) 751 753 return 0; ··· 790 792 mod_name = find_module_name(module); 791 793 for (i = 0; i < ntevs; i++) { 792 794 ret = post_process_probe_trace_point(&tevs[i].point, 793 - map, (unsigned long)text_offs); 795 + map, text_offs); 794 796 if (ret < 0) 795 797 break; 796 798 tevs[i].point.module = ··· 1534 1536 * so tmp[1] should always valid (but could be '\0'). 1535 1537 */ 1536 1538 if (tmp && !strncmp(tmp, "0x", 2)) { 1537 - pp->abs_address = strtoul(pp->function, &tmp, 0); 1539 + pp->abs_address = strtoull(pp->function, &tmp, 0); 1538 1540 if (*tmp != '\0') { 1539 1541 semantic_error("Invalid absolute address.\n"); 1540 1542 return -EINVAL; ··· 1909 1911 argv[i] = NULL; 1910 1912 argc -= 1; 1911 1913 } else 1912 - tp->address = strtoul(fmt1_str, NULL, 0); 1914 + tp->address = strtoull(fmt1_str, NULL, 0); 1913 1915 } else { 1914 1916 /* Only the symbol-based probe has offset */ 1915 1917 tp->symbol = strdup(fmt1_str); ··· 2155 2157 return -EINVAL; 2156 2158 2157 2159 /* Use the tp->address for uprobes */ 2158 - err = strbuf_addf(buf, "%s:0x%lx", tp->module, tp->address); 2160 + err = strbuf_addf(buf, "%s:0x%" PRIx64, tp->module, tp->address); 2159 2161 2160 2162 if (err >= 0 && tp->ref_ctr_offset) { 2161 2163 if (!uprobe_ref_ctr_is_supported()) ··· 2170 2172 { 2171 2173 if (!strncmp(tp->symbol, "0x", 2)) { 2172 2174 /* Absolute address. See try_to_find_absolute_address() */ 2173 - return strbuf_addf(buf, "%s%s0x%lx", tp->module ?: "", 2175 + return strbuf_addf(buf, "%s%s0x%" PRIx64, tp->module ?: "", 2174 2176 tp->module ? ":" : "", tp->address); 2175 2177 } else { 2176 2178 return strbuf_addf(buf, "%s%s%s+%lu", tp->module ?: "", ··· 2269 2271 pp->function = strdup(tp->symbol); 2270 2272 pp->offset = tp->offset; 2271 2273 } else { 2272 - ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address); 2274 + ret = e_snprintf(buf, 128, "0x%" PRIx64, tp->address); 2273 2275 if (ret < 0) 2274 2276 return ret; 2275 2277 pp->function = strdup(buf); ··· 2450 2452 2451 2453 struct kprobe_blacklist_node { 2452 2454 struct list_head list; 2453 - unsigned long start; 2454 - unsigned long end; 2455 + u64 start; 2456 + u64 end; 2455 2457 char *symbol; 2456 2458 }; 2457 2459 ··· 2496 2498 } 2497 2499 INIT_LIST_HEAD(&node->list); 2498 2500 list_add_tail(&node->list, blacklist); 2499 - if (sscanf(buf, "0x%lx-0x%lx", &node->start, &node->end) != 2) { 2501 + if (sscanf(buf, "0x%" PRIx64 "-0x%" PRIx64, &node->start, &node->end) != 2) { 2500 2502 ret = -EINVAL; 2501 2503 break; 2502 2504 } ··· 2512 2514 ret = -ENOMEM; 2513 2515 break; 2514 2516 } 2515 - pr_debug2("Blacklist: 0x%lx-0x%lx, %s\n", 2517 + pr_debug2("Blacklist: 0x%" PRIx64 "-0x%" PRIx64 ", %s\n", 2516 2518 node->start, node->end, node->symbol); 2517 2519 ret++; 2518 2520 } ··· 2524 2526 } 2525 2527 2526 2528 static struct kprobe_blacklist_node * 2527 - kprobe_blacklist__find_by_address(struct list_head *blacklist, 2528 - unsigned long address) 2529 + kprobe_blacklist__find_by_address(struct list_head *blacklist, u64 address) 2529 2530 { 2530 2531 struct kprobe_blacklist_node *node; 2531 2532 ··· 2552 2555 kprobe_blacklist__delete(&kprobe_blacklist); 2553 2556 } 2554 2557 2555 - static bool kprobe_blacklist__listed(unsigned long address) 2558 + static bool kprobe_blacklist__listed(u64 address) 2556 2559 { 2557 2560 return !!kprobe_blacklist__find_by_address(&kprobe_blacklist, address); 2558 2561 } ··· 3220 3223 * In __add_probe_trace_events, a NULL symbol is interpreted as 3221 3224 * invalid. 3222 3225 */ 3223 - if (asprintf(&tp->symbol, "0x%lx", tp->address) < 0) 3226 + if (asprintf(&tp->symbol, "0x%" PRIx64, tp->address) < 0) 3224 3227 goto errout; 3225 3228 3226 3229 /* For kprobe, check range */ ··· 3231 3234 goto errout; 3232 3235 } 3233 3236 3234 - if (asprintf(&tp->realname, "abs_%lx", tp->address) < 0) 3237 + if (asprintf(&tp->realname, "abs_%" PRIx64, tp->address) < 0) 3235 3238 goto errout; 3236 3239 3237 3240 if (pev->target) {
+2 -2
tools/perf/util/probe-event.h
··· 33 33 char *module; /* Module name */ 34 34 unsigned long offset; /* Offset from symbol */ 35 35 unsigned long ref_ctr_offset; /* SDT reference counter offset */ 36 - unsigned long address; /* Actual address of the trace point */ 36 + u64 address; /* Actual address of the trace point */ 37 37 bool retprobe; /* Return probe flag */ 38 38 }; 39 39 ··· 70 70 bool retprobe; /* Return probe flag */ 71 71 char *lazy_line; /* Lazy matching pattern */ 72 72 unsigned long offset; /* Offset from function entry */ 73 - unsigned long abs_address; /* Absolute address of the point */ 73 + u64 abs_address; /* Absolute address of the point */ 74 74 }; 75 75 76 76 /* Perf probe probing argument field chain */
+7 -8
tools/perf/util/probe-finder.c
··· 668 668 } 669 669 670 670 tp->offset = (unsigned long)(paddr - eaddr); 671 - tp->address = (unsigned long)paddr; 671 + tp->address = paddr; 672 672 tp->symbol = strdup(symbol); 673 673 if (!tp->symbol) 674 674 return -ENOMEM; ··· 1707 1707 } 1708 1708 1709 1709 /* Reverse search */ 1710 - int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, 1710 + int debuginfo__find_probe_point(struct debuginfo *dbg, u64 addr, 1711 1711 struct perf_probe_point *ppt) 1712 1712 { 1713 1713 Dwarf_Die cudie, spdie, indie; ··· 1720 1720 addr += baseaddr; 1721 1721 /* Find cu die */ 1722 1722 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) { 1723 - pr_warning("Failed to find debug information for address %lx\n", 1723 + pr_warning("Failed to find debug information for address %" PRIx64 "\n", 1724 1724 addr); 1725 1725 ret = -EINVAL; 1726 1726 goto end; 1727 1727 } 1728 1728 1729 1729 /* Find a corresponding line (filename and lineno) */ 1730 - cu_find_lineinfo(&cudie, addr, &fname, &lineno); 1730 + cu_find_lineinfo(&cudie, (Dwarf_Addr)addr, &fname, &lineno); 1731 1731 /* Don't care whether it failed or not */ 1732 1732 1733 1733 /* Find a corresponding function (name, baseline and baseaddr) */ ··· 1742 1742 } 1743 1743 1744 1744 fname = dwarf_decl_file(&spdie); 1745 - if (addr == (unsigned long)baseaddr) { 1745 + if (addr == baseaddr) { 1746 1746 /* Function entry - Relative line number is 0 */ 1747 1747 lineno = baseline; 1748 1748 goto post; ··· 1788 1788 if (lineno) 1789 1789 ppt->line = lineno - baseline; 1790 1790 else if (basefunc) { 1791 - ppt->offset = addr - (unsigned long)baseaddr; 1791 + ppt->offset = addr - baseaddr; 1792 1792 func = basefunc; 1793 1793 } 1794 1794 ··· 1828 1828 } 1829 1829 1830 1830 static int line_range_walk_cb(const char *fname, int lineno, 1831 - Dwarf_Addr addr __maybe_unused, 1832 - void *data) 1831 + Dwarf_Addr addr, void *data) 1833 1832 { 1834 1833 struct line_finder *lf = data; 1835 1834 const char *__fname;
+1 -1
tools/perf/util/probe-finder.h
··· 46 46 struct probe_trace_event **tevs); 47 47 48 48 /* Find a perf_probe_point from debuginfo */ 49 - int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, 49 + int debuginfo__find_probe_point(struct debuginfo *dbg, u64 addr, 50 50 struct perf_probe_point *ppt); 51 51 52 52 int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,