Skip to content

Commit 22a6655

Browse files
Yang Jihongacmel
authored andcommitted
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 <[email protected]> Acked-by: Masami Hiramatsu <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Frank Ch. Eigler <[email protected]> Cc: Ian Rogers <[email protected]> Cc: Jianlin Lv <[email protected]> Cc: Jin Yao <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Li Huafei <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Ravi Bangoria <[email protected]> Cc: Srikar Dronamraju <[email protected]> Link: http://lore.kernel.org/lkml/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent d4b3eed commit 22a6655

File tree

6 files changed

+38
-42
lines changed

6 files changed

+38
-42
lines changed

tools/perf/util/dwarf-aux.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,22 +113,22 @@ static Dwarf_Line *cu_getsrc_die(Dwarf_Die *cu_die, Dwarf_Addr addr)
113113
*
114114
* Find a line number and file name for @addr in @cu_die.
115115
*/
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)
118118
{
119119
Dwarf_Line *line;
120120
Dwarf_Die die_mem;
121121
Dwarf_Addr faddr;
122122

123-
if (die_find_realfunc(cu_die, (Dwarf_Addr)addr, &die_mem)
123+
if (die_find_realfunc(cu_die, addr, &die_mem)
124124
&& die_entrypc(&die_mem, &faddr) == 0 &&
125125
faddr == addr) {
126126
*fname = dwarf_decl_file(&die_mem);
127127
dwarf_decl_line(&die_mem, lineno);
128128
goto out;
129129
}
130130

131-
line = cu_getsrc_die(cu_die, (Dwarf_Addr)addr);
131+
line = cu_getsrc_die(cu_die, addr);
132132
if (line && dwarf_lineno(line, lineno) == 0) {
133133
*fname = dwarf_linesrc(line, NULL, NULL);
134134
if (!*fname)

tools/perf/util/dwarf-aux.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname);
1919
const char *cu_get_comp_dir(Dwarf_Die *cu_die);
2020

2121
/* 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,
2323
const char **fname, int *lineno);
2424

2525
/* Walk on functions at given address */

tools/perf/util/probe-event.c

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,8 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
239239
clear_probe_trace_event(tevs + i);
240240
}
241241

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)
244244
{
245245
struct map *map;
246246
bool ret = false;
@@ -400,8 +400,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo,
400400
pr_debug("Symbol %s address found : %" PRIx64 "\n",
401401
pp->function, address);
402402

403-
ret = debuginfo__find_probe_point(dinfo, (unsigned long)address,
404-
result);
403+
ret = debuginfo__find_probe_point(dinfo, address, result);
405404
if (ret <= 0)
406405
ret = (!ret) ? -ENOENT : ret;
407406
else {
@@ -589,7 +588,7 @@ static void debuginfo_cache__exit(void)
589588
}
590589

591590

592-
static int get_text_start_address(const char *exec, unsigned long *address,
591+
static int get_text_start_address(const char *exec, u64 *address,
593592
struct nsinfo *nsi)
594593
{
595594
Elf *elf;
@@ -634,7 +633,7 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
634633
bool is_kprobe)
635634
{
636635
struct debuginfo *dinfo = NULL;
637-
unsigned long stext = 0;
636+
u64 stext = 0;
638637
u64 addr = tp->address;
639638
int ret = -ENOENT;
640639

@@ -662,8 +661,7 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
662661

663662
dinfo = debuginfo_cache__open(tp->module, verbose <= 0);
664663
if (dinfo)
665-
ret = debuginfo__find_probe_point(dinfo,
666-
(unsigned long)addr, pp);
664+
ret = debuginfo__find_probe_point(dinfo, addr, pp);
667665
else
668666
ret = -ENOENT;
669667

@@ -678,7 +676,7 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
678676

679677
/* Adjust symbol name and address */
680678
static int post_process_probe_trace_point(struct probe_trace_point *tp,
681-
struct map *map, unsigned long offs)
679+
struct map *map, u64 offs)
682680
{
683681
struct symbol *sym;
684682
u64 addr = tp->address - offs;
@@ -721,7 +719,7 @@ post_process_offline_probe_trace_events(struct probe_trace_event *tevs,
721719
int ntevs, const char *pathname)
722720
{
723721
struct map *map;
724-
unsigned long stext = 0;
722+
u64 stext = 0;
725723
int i, ret = 0;
726724

727725
/* Prepare a map for offline binary */
@@ -747,7 +745,7 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
747745
struct nsinfo *nsi)
748746
{
749747
int i, ret = 0;
750-
unsigned long stext = 0;
748+
u64 stext = 0;
751749

752750
if (!exec)
753751
return 0;
@@ -792,7 +790,7 @@ post_process_module_probe_trace_events(struct probe_trace_event *tevs,
792790
mod_name = find_module_name(module);
793791
for (i = 0; i < ntevs; i++) {
794792
ret = post_process_probe_trace_point(&tevs[i].point,
795-
map, (unsigned long)text_offs);
793+
map, text_offs);
796794
if (ret < 0)
797795
break;
798796
tevs[i].point.module =
@@ -1536,7 +1534,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
15361534
* so tmp[1] should always valid (but could be '\0').
15371535
*/
15381536
if (tmp && !strncmp(tmp, "0x", 2)) {
1539-
pp->abs_address = strtoul(pp->function, &tmp, 0);
1537+
pp->abs_address = strtoull(pp->function, &tmp, 0);
15401538
if (*tmp != '\0') {
15411539
semantic_error("Invalid absolute address.\n");
15421540
return -EINVAL;
@@ -1911,7 +1909,7 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
19111909
argv[i] = NULL;
19121910
argc -= 1;
19131911
} else
1914-
tp->address = strtoul(fmt1_str, NULL, 0);
1912+
tp->address = strtoull(fmt1_str, NULL, 0);
19151913
} else {
19161914
/* Only the symbol-based probe has offset */
19171915
tp->symbol = strdup(fmt1_str);
@@ -2157,7 +2155,7 @@ synthesize_uprobe_trace_def(struct probe_trace_point *tp, struct strbuf *buf)
21572155
return -EINVAL;
21582156

21592157
/* Use the tp->address for uprobes */
2160-
err = strbuf_addf(buf, "%s:0x%lx", tp->module, tp->address);
2158+
err = strbuf_addf(buf, "%s:0x%" PRIx64, tp->module, tp->address);
21612159

21622160
if (err >= 0 && tp->ref_ctr_offset) {
21632161
if (!uprobe_ref_ctr_is_supported())
@@ -2172,7 +2170,7 @@ synthesize_kprobe_trace_def(struct probe_trace_point *tp, struct strbuf *buf)
21722170
{
21732171
if (!strncmp(tp->symbol, "0x", 2)) {
21742172
/* Absolute address. See try_to_find_absolute_address() */
2175-
return strbuf_addf(buf, "%s%s0x%lx", tp->module ?: "",
2173+
return strbuf_addf(buf, "%s%s0x%" PRIx64, tp->module ?: "",
21762174
tp->module ? ":" : "", tp->address);
21772175
} else {
21782176
return strbuf_addf(buf, "%s%s%s+%lu", tp->module ?: "",
@@ -2271,7 +2269,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp,
22712269
pp->function = strdup(tp->symbol);
22722270
pp->offset = tp->offset;
22732271
} else {
2274-
ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address);
2272+
ret = e_snprintf(buf, 128, "0x%" PRIx64, tp->address);
22752273
if (ret < 0)
22762274
return ret;
22772275
pp->function = strdup(buf);
@@ -2452,8 +2450,8 @@ void clear_probe_trace_event(struct probe_trace_event *tev)
24522450

24532451
struct kprobe_blacklist_node {
24542452
struct list_head list;
2455-
unsigned long start;
2456-
unsigned long end;
2453+
u64 start;
2454+
u64 end;
24572455
char *symbol;
24582456
};
24592457

@@ -2498,7 +2496,7 @@ static int kprobe_blacklist__load(struct list_head *blacklist)
24982496
}
24992497
INIT_LIST_HEAD(&node->list);
25002498
list_add_tail(&node->list, blacklist);
2501-
if (sscanf(buf, "0x%lx-0x%lx", &node->start, &node->end) != 2) {
2499+
if (sscanf(buf, "0x%" PRIx64 "-0x%" PRIx64, &node->start, &node->end) != 2) {
25022500
ret = -EINVAL;
25032501
break;
25042502
}
@@ -2514,7 +2512,7 @@ static int kprobe_blacklist__load(struct list_head *blacklist)
25142512
ret = -ENOMEM;
25152513
break;
25162514
}
2517-
pr_debug2("Blacklist: 0x%lx-0x%lx, %s\n",
2515+
pr_debug2("Blacklist: 0x%" PRIx64 "-0x%" PRIx64 ", %s\n",
25182516
node->start, node->end, node->symbol);
25192517
ret++;
25202518
}
@@ -2526,8 +2524,7 @@ static int kprobe_blacklist__load(struct list_head *blacklist)
25262524
}
25272525

25282526
static struct kprobe_blacklist_node *
2529-
kprobe_blacklist__find_by_address(struct list_head *blacklist,
2530-
unsigned long address)
2527+
kprobe_blacklist__find_by_address(struct list_head *blacklist, u64 address)
25312528
{
25322529
struct kprobe_blacklist_node *node;
25332530

@@ -2555,7 +2552,7 @@ static void kprobe_blacklist__release(void)
25552552
kprobe_blacklist__delete(&kprobe_blacklist);
25562553
}
25572554

2558-
static bool kprobe_blacklist__listed(unsigned long address)
2555+
static bool kprobe_blacklist__listed(u64 address)
25592556
{
25602557
return !!kprobe_blacklist__find_by_address(&kprobe_blacklist, address);
25612558
}
@@ -3223,7 +3220,7 @@ static int try_to_find_absolute_address(struct perf_probe_event *pev,
32233220
* In __add_probe_trace_events, a NULL symbol is interpreted as
32243221
* invalid.
32253222
*/
3226-
if (asprintf(&tp->symbol, "0x%lx", tp->address) < 0)
3223+
if (asprintf(&tp->symbol, "0x%" PRIx64, tp->address) < 0)
32273224
goto errout;
32283225

32293226
/* For kprobe, check range */
@@ -3234,7 +3231,7 @@ static int try_to_find_absolute_address(struct perf_probe_event *pev,
32343231
goto errout;
32353232
}
32363233

3237-
if (asprintf(&tp->realname, "abs_%lx", tp->address) < 0)
3234+
if (asprintf(&tp->realname, "abs_%" PRIx64, tp->address) < 0)
32383235
goto errout;
32393236

32403237
if (pev->target) {

tools/perf/util/probe-event.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ struct probe_trace_point {
3333
char *module; /* Module name */
3434
unsigned long offset; /* Offset from symbol */
3535
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 */
3737
bool retprobe; /* Return probe flag */
3838
};
3939

@@ -70,7 +70,7 @@ struct perf_probe_point {
7070
bool retprobe; /* Return probe flag */
7171
char *lazy_line; /* Lazy matching pattern */
7272
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 */
7474
};
7575

7676
/* Perf probe probing argument field chain */

tools/perf/util/probe-finder.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
668668
}
669669

670670
tp->offset = (unsigned long)(paddr - eaddr);
671-
tp->address = (unsigned long)paddr;
671+
tp->address = paddr;
672672
tp->symbol = strdup(symbol);
673673
if (!tp->symbol)
674674
return -ENOMEM;
@@ -1707,7 +1707,7 @@ int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
17071707
}
17081708

17091709
/* 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,
17111711
struct perf_probe_point *ppt)
17121712
{
17131713
Dwarf_Die cudie, spdie, indie;
@@ -1720,14 +1720,14 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
17201720
addr += baseaddr;
17211721
/* Find cu die */
17221722
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",
17241724
addr);
17251725
ret = -EINVAL;
17261726
goto end;
17271727
}
17281728

17291729
/* 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);
17311731
/* Don't care whether it failed or not */
17321732

17331733
/* Find a corresponding function (name, baseline and baseaddr) */
@@ -1742,7 +1742,7 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
17421742
}
17431743

17441744
fname = dwarf_decl_file(&spdie);
1745-
if (addr == (unsigned long)baseaddr) {
1745+
if (addr == baseaddr) {
17461746
/* Function entry - Relative line number is 0 */
17471747
lineno = baseline;
17481748
goto post;
@@ -1788,7 +1788,7 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
17881788
if (lineno)
17891789
ppt->line = lineno - baseline;
17901790
else if (basefunc) {
1791-
ppt->offset = addr - (unsigned long)baseaddr;
1791+
ppt->offset = addr - baseaddr;
17921792
func = basefunc;
17931793
}
17941794

@@ -1828,8 +1828,7 @@ static int line_range_add_line(const char *src, unsigned int lineno,
18281828
}
18291829

18301830
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)
18331832
{
18341833
struct line_finder *lf = data;
18351834
const char *__fname;

tools/perf/util/probe-finder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,
4646
struct probe_trace_event **tevs);
4747

4848
/* 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,
5050
struct perf_probe_point *ppt);
5151

5252
int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,

0 commit comments

Comments
 (0)