Skip to content

Commit 28cb835

Browse files
captain5050acmel
authored andcommitted
perf machine: Add inline information to frame pointer and LBR callchains
Use append_inlines() in frame pointer and LBR cases. Update the addr2line test to also test frame pointers. LBR is also updated but inaccuracy in the branched to IP means the inline information is missing in the leaf. Leave LBR callchains untested for now. Signed-off-by: Ian Rogers <[email protected]> Cc: Aditya Bodkhe <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Albert Ou <[email protected]> Cc: Alexandre Ghiti <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Athira Rajeev <[email protected]> Cc: Chun-Tse Shao <[email protected]> Cc: Dmitriy Vyukov <[email protected]> Cc: Dr. David Alan Gilbert <[email protected]> Cc: Guo Ren <[email protected]> Cc: Haibo Xu <[email protected]> Cc: Howard Chu <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: James Clark <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: John Garry <[email protected]> Cc: Krzysztof Łopatowski <[email protected]> Cc: Leo Yan <[email protected]> Cc: Mark Wielaard <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Palmer Dabbelt <[email protected]> Cc: Paul Walmsley <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Sergei Trofimovich <[email protected]> Cc: Shimin Guo <[email protected]> Cc: Stephen Brennan <[email protected]> Cc: Thomas Falcon <[email protected]> Cc: Will Deacon <[email protected]> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 6b2658b commit 28cb835

2 files changed

Lines changed: 86 additions & 49 deletions

File tree

tools/perf/tests/shell/addr2line_inlines.sh

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,28 @@ trap_cleanup() {
2121
}
2222
trap trap_cleanup EXIT TERM INT
2323

24-
test_inlinedloop() {
25-
echo "Inline unwinding verification test"
24+
test_fp() {
25+
echo "Inline unwinding fp verification test"
26+
# Record data. Currently only dwarf callchains support inlined functions.
27+
perf record --call-graph fp -e task-clock:u -o "${perf_data}" -- perf test -w inlineloop 1
28+
29+
# Check output with inline (default) and srcline
30+
perf script -i "${perf_data}" --fields +srcline > "${perf_script_txt}"
31+
32+
# Expect the leaf and middle functions to occur on lines in the 20s, with
33+
# the non-inlined parent function on a line in the 30s.
34+
if grep -q "inlineloop.c:2. (inlined)" "${perf_script_txt}" &&
35+
grep -q "inlineloop.c:3.$" "${perf_script_txt}"
36+
then
37+
echo "Inline unwinding fp verification test [Success]"
38+
else
39+
echo "Inline unwinding fp verification test [Failed missing inlined functions]"
40+
err=1
41+
fi
42+
}
43+
44+
test_dwarf() {
45+
echo "Inline unwinding dwarf verification test"
2646
# Record data. Currently only dwarf callchains support inlined functions.
2747
perf record --call-graph dwarf -e task-clock:u -o "${perf_data}" -- perf test -w inlineloop 1
2848

@@ -34,14 +54,15 @@ test_inlinedloop() {
3454
if grep -q "inlineloop.c:2. (inlined)" "${perf_script_txt}" &&
3555
grep -q "inlineloop.c:3.$" "${perf_script_txt}"
3656
then
37-
echo "Inline unwinding verification test [Success]"
57+
echo "Inline unwinding dwarf verification test [Success]"
3858
else
39-
echo "Inline unwinding verification test [Failed missing inlined functions]"
59+
echo "Inline unwinding dwarf verification test [Failed missing inlined functions]"
4060
err=1
4161
fi
4262
}
4363

44-
test_inlinedloop
64+
test_fp
65+
test_dwarf
4566

4667
cleanup
4768
exit $err

tools/perf/util/machine.c

Lines changed: 60 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,6 +2090,59 @@ struct iterations {
20902090
u64 cycles;
20912091
};
20922092

2093+
static int append_inlines(struct callchain_cursor *cursor, struct map_symbol *ms, u64 ip,
2094+
bool branch, struct branch_flags *flags, int nr_loop_iter,
2095+
u64 iter_cycles, u64 branch_from)
2096+
{
2097+
struct symbol *sym = ms->sym;
2098+
struct map *map = ms->map;
2099+
struct inline_node *inline_node;
2100+
struct inline_list *ilist;
2101+
struct dso *dso;
2102+
u64 addr;
2103+
int ret = 1;
2104+
struct map_symbol ilist_ms;
2105+
bool first = true;
2106+
2107+
if (!symbol_conf.inline_name || !map || !sym)
2108+
return ret;
2109+
2110+
addr = map__dso_map_ip(map, ip);
2111+
addr = map__rip_2objdump(map, addr);
2112+
dso = map__dso(map);
2113+
2114+
inline_node = inlines__tree_find(dso__inlined_nodes(dso), addr);
2115+
if (!inline_node) {
2116+
inline_node = dso__parse_addr_inlines(dso, addr, sym);
2117+
if (!inline_node)
2118+
return ret;
2119+
inlines__tree_insert(dso__inlined_nodes(dso), inline_node);
2120+
}
2121+
2122+
ilist_ms = (struct map_symbol) {
2123+
.maps = maps__get(ms->maps),
2124+
.map = map__get(map),
2125+
};
2126+
list_for_each_entry(ilist, &inline_node->val, list) {
2127+
ilist_ms.sym = ilist->symbol;
2128+
if (first) {
2129+
ret = callchain_cursor_append(cursor, ip, &ilist_ms,
2130+
branch, flags, nr_loop_iter,
2131+
iter_cycles, branch_from, ilist->srcline);
2132+
} else {
2133+
ret = callchain_cursor_append(cursor, ip, &ilist_ms, false,
2134+
NULL, 0, 0, 0, ilist->srcline);
2135+
}
2136+
first = false;
2137+
2138+
if (ret != 0)
2139+
return ret;
2140+
}
2141+
map_symbol__exit(&ilist_ms);
2142+
2143+
return ret;
2144+
}
2145+
20932146
static int add_callchain_ip(struct thread *thread,
20942147
struct callchain_cursor *cursor,
20952148
struct symbol **parent,
@@ -2170,6 +2223,11 @@ static int add_callchain_ip(struct thread *thread,
21702223
ms.maps = maps__get(al.maps);
21712224
ms.map = map__get(al.map);
21722225
ms.sym = al.sym;
2226+
2227+
if (append_inlines(cursor, &ms, ip, branch, flags, nr_loop_iter,
2228+
iter_cycles, branch_from) == 0)
2229+
goto out;
2230+
21732231
srcline = callchain_srcline(&ms, al.addr);
21742232
err = callchain_cursor_append(cursor, ip, &ms,
21752233
branch, flags, nr_loop_iter,
@@ -2888,49 +2946,6 @@ static int thread__resolve_callchain_sample(struct thread *thread,
28882946
return 0;
28892947
}
28902948

2891-
static int append_inlines(struct callchain_cursor *cursor, struct map_symbol *ms, u64 ip)
2892-
{
2893-
struct symbol *sym = ms->sym;
2894-
struct map *map = ms->map;
2895-
struct inline_node *inline_node;
2896-
struct inline_list *ilist;
2897-
struct dso *dso;
2898-
u64 addr;
2899-
int ret = 1;
2900-
struct map_symbol ilist_ms;
2901-
2902-
if (!symbol_conf.inline_name || !map || !sym)
2903-
return ret;
2904-
2905-
addr = map__dso_map_ip(map, ip);
2906-
addr = map__rip_2objdump(map, addr);
2907-
dso = map__dso(map);
2908-
2909-
inline_node = inlines__tree_find(dso__inlined_nodes(dso), addr);
2910-
if (!inline_node) {
2911-
inline_node = dso__parse_addr_inlines(dso, addr, sym);
2912-
if (!inline_node)
2913-
return ret;
2914-
inlines__tree_insert(dso__inlined_nodes(dso), inline_node);
2915-
}
2916-
2917-
ilist_ms = (struct map_symbol) {
2918-
.maps = maps__get(ms->maps),
2919-
.map = map__get(map),
2920-
};
2921-
list_for_each_entry(ilist, &inline_node->val, list) {
2922-
ilist_ms.sym = ilist->symbol;
2923-
ret = callchain_cursor_append(cursor, ip, &ilist_ms, false,
2924-
NULL, 0, 0, 0, ilist->srcline);
2925-
2926-
if (ret != 0)
2927-
return ret;
2928-
}
2929-
map_symbol__exit(&ilist_ms);
2930-
2931-
return ret;
2932-
}
2933-
29342949
static int unwind_entry(struct unwind_entry *entry, void *arg)
29352950
{
29362951
struct callchain_cursor *cursor = arg;
@@ -2940,7 +2955,8 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
29402955
if (symbol_conf.hide_unresolved && entry->ms.sym == NULL)
29412956
return 0;
29422957

2943-
if (append_inlines(cursor, &entry->ms, entry->ip) == 0)
2958+
if (append_inlines(cursor, &entry->ms, entry->ip, /*branch=*/false, /*branch_flags=*/NULL,
2959+
/*nr_loop_iter=*/0, /*iter_cycles=*/0, /*branch_from=*/0) == 0)
29442960
return 0;
29452961

29462962
/*

0 commit comments

Comments
 (0)