2022-12-19 09:04:59

by Thomas Richter

[permalink] [raw]
Subject: [PATCH v3 1/2] perf/test: Fix perf test 84 on s390

perf test '84: probe libc's inet_pton & backtrace it with ping'
fails on s390. Debugging revealed a changed stack trace for the
ping command using probes:

ping 35729 [002] 8006.365063: probe_libc:inet_pton: (3ff9603e7c0)
13e7c0 __GI___inet_pton+0x0 (/usr/lib64/libc.so.6)
---> 104371 text_to_binary_address+0xef1 (inlined)
104371 gaih_inet+0xef1 (inlined)
104371 __GI_getaddrinfo+0xef1 (inlined)
5d4b main+0x139b (/usr/bin/ping)

The line ---> text_to_binary_address ...
is new. It was introduced with glibc version 2.36.7.2 released
with Fedora 37 for s390.

Output before
# ./perf test 84
84: probe libc's inet_pton & backtrace it with ping : FAILED!
#

Output after:
# ./perf test 84
84: probe libc's inet_pton & backtrace it with ping : Ok
#

Signed-off-by: Thomas Richter <[email protected]>
---
tools/perf/tests/shell/record+probe_libc_inet_pton.sh | 1 +
1 file changed, 1 insertion(+)

diff --git a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
index f12a4e217968..0f01c62cbee9 100755
--- a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
+++ b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
@@ -37,6 +37,7 @@ trace_libc_inet_pton_backtrace() {
case "$(uname -m)" in
s390x)
eventattr='call-graph=dwarf,max-stack=4'
+ echo "text_to_binary_address.*\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$" >> $expected
echo "gaih_inet.*\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$" >> $expected
echo "(__GI_)?getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$" >> $expected
echo "main\+0x[[:xdigit:]]+[[:space:]]\(.*/bin/ping.*\)$" >> $expected
--
2.38.1


2022-12-19 09:10:01

by Thomas Richter

[permalink] [raw]
Subject: [PATCH v3 2/2] perf/test: Fix test case 89 for x86

perf test '89: probe libc's inet_pton & backtrace it with ping'
fails on x86. Debugging revealed a changed stack trace for the
ping command using probes:

ping 35729 [002] 8006.365063: probe_libc:inet_pton: (3ff9603e7c0)
12be50 __GI___inet_pton+0x0 (/usr/lib64/libc.so.6)
4fca main+0x139b (/usr/bin/ping)

The line getaddrinfo.... in the call stack is gone.
It was introduced with glibc version 2.36.8 released
with Fedora 37.

To make the test case more robust to glibc changes resulting in changed
call stack, redesign the test completely.
Read the output lines from the perf probe of the ping command.
Create an array of expected patterns. Each array entry specifies a
pattern that may appear in the perf probe output.
Check that each probe output line is matched in the expected
patterns array. If there is no match it is an error.
However not every pattern in the expected pattern array must be hit
as there may be redundant entries.

This scheme does not test the sequence of the call stack but the
patterns itself are long and complicated enough. This should be
ok.

Output before on x86
# ./perf test 89
89: probe libc's inet_pton & backtrace it with ping : FAILED!
#

Output after on x86
# ./perf test 89
89: probe libc's inet_pton & backtrace it with ping : Ok
#

Signed-off-by: Thomas Richter <[email protected]>
---
.../shell/record+probe_libc_inet_pton.sh | 70 +++++++++++++------
1 file changed, 48 insertions(+), 22 deletions(-)

diff --git a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
index 0f01c62cbee9..5b424be76716 100755
--- a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
+++ b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
@@ -30,28 +30,36 @@ add_libc_inet_pton_event() {

trace_libc_inet_pton_backtrace() {

- expected=`mktemp -u /tmp/expected.XXX`
+ declare -a expected
+ local -i idx=0 hit maxstack=4

- echo "ping[][0-9 \.:]+$event_name: \([[:xdigit:]]+\)" > $expected
- echo ".*inet_pton\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$" >> $expected
+ expected[0]='ping[][0-9 \.:]+'"$event_name"': \([[:xdigit:]]+\)'
+ expected[1]='.*inet_pton\+0x[[:xdigit:]]+[[:space:]]\('"$libc"'|inlined\)$'
case "$(uname -m)" in
s390x)
- eventattr='call-graph=dwarf,max-stack=4'
- echo "text_to_binary_address.*\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$" >> $expected
- echo "gaih_inet.*\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$" >> $expected
- echo "(__GI_)?getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$" >> $expected
- echo "main\+0x[[:xdigit:]]+[[:space:]]\(.*/bin/ping.*\)$" >> $expected
+ eventattr='call-graph=dwarf,max-stack='"$maxstack"
+ expected[2]='text_to_binary_address.*\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$'
+ expected[3]='gaih_inet.*\+0x[[:xdigit:]]+[[:space:]]\('"$libc"'|inlined\)$'
+ expected[4]='(__GI_)?getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\('"$libc"'|inlined\)$'
+ expected[5]='main\+0x[[:xdigit:]]+[[:space:]]\(.*/bin/ping.*\)$'
;;
ppc64|ppc64le)
- eventattr='max-stack=4'
- echo "gaih_inet.*\+0x[[:xdigit:]]+[[:space:]]\($libc\)$" >> $expected
- echo "getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc\)$" >> $expected
- echo ".*(\+0x[[:xdigit:]]+|\[unknown\])[[:space:]]\(.*/bin/ping.*\)$" >> $expected
+ eventattr='max-stack='"$maxstack"
+ expected[2]='gaih_inet.*\+0x[[:xdigit:]]+[[:space:]]\('"$libc"'\)$'
+ expected[3]='getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\('"$libc"'\)$'
+ # Line valid with glibc 2.35.x with fedora 36
+ expected[4]='.*(\+0x[[:xdigit:]]+|\[unknown\])[[:space:]]\(.*/bin/ping.*\)$'
+ # New line introduced with glibc 2.36.x with fedora 37, replaces previous line
+ expected[5]='[[:xdigit:]]+[[:space:]](\[unknown\]|main)\+0x[[:xdigit:]]+.*\(.*/bin/ping.*\)$'
;;
*)
- eventattr='max-stack=3'
- echo "getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc\)$" >> $expected
- echo ".*(\+0x[[:xdigit:]]+|\[unknown\])[[:space:]]\(.*/bin/ping.*\)$" >> $expected
+ maxstack=3
+ eventattr='max-stack='"$maxstack"
+ expected[2]='getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\('"$libc"'\)$'
+ # Line valid with glibc 2.35.x with fedora 36
+ expected[3]='.*(\+0x[[:xdigit:]]+|\[unknown\])[[:space:]]\(.*/bin/ping.*\)$'
+ # New line introduced with glibc 2.36.x with fedora 37, replaces previous line
+ expected[4]='[[:xdigit:]]+[[:space:]](\[unknown\]|main)\+0x[[:xdigit:]]+.*\(.*/bin/ping.*\)$'
;;
esac

@@ -60,16 +68,34 @@ trace_libc_inet_pton_backtrace() {
perf record -e $event_name/$eventattr/ -o $perf_data ping -6 -c 1 ::1 > /dev/null 2>&1
perf script -i $perf_data > $perf_script

+ # To make the call stack checking more robust to changes in the glibc
+ # just check that each probe output line appears in the expected
+ # patterns array.
+ # This scheme does not check the sequence as before but tests
+ # that every line in the call stack is expected. Considering the
+ # long patterns this should be save too.
exec 3<$perf_script
- exec 4<$expected
- while read line <&3 && read -r pattern <&4; do
- [ -z "$pattern" ] && break
- echo $line
- echo "$line" | egrep -q "$pattern"
- if [ $? -ne 0 ] ; then
- printf "FAIL: expected backtrace entry \"%s\" got \"%s\"\n" "$pattern" "$line"
+
+ # Number of input lines to check, take value from max-stack attribute
+ while read line <&3; do
+ [ "$idx" -ge "$maxstack" ] && break
+ [ -z "$line" ] && break
+
+ hit=0
+ for pattern in "${expected[@]}"
+ do
+ # echo PATTERN "$pattern"
+ echo "$line" | egrep -q "$pattern"
+ [ $? -eq 0 ] && { hit=1; break; }
+ done
+ if [ "$hit" -eq 1 ]
+ then
+ printf "HIT: \"%s\"\n" "$line"
+ else
+ printf "FAIL: missing backtrace entry for line \"%s\"\n" "$line"
return 1
fi
+ ((++idx))
done

# If any statements are executed from this point onwards,
--
2.38.1