1# probe libc's inet_pton & backtrace it with ping
2
3# Installs a probe on libc's inet_pton function, that will use uprobes,
4# then use 'perf trace' on a ping to localhost asking for just one packet
5# with the a backtrace 3 levels deep, check that it is what we expect.
6# This needs no debuginfo package, all is done using the libc ELF symtab
7# and the CFI info in the binaries.
8
9# Arnaldo Carvalho de Melo <acme@kernel.org>, 2017
10
11. $(dirname $0)/lib/probe.sh
12
13libc=$(grep -w libc /proc/self/maps | head -1 | sed -r 's/.*[[:space:]](\/.*)/\1/g')
14nm -g $libc 2>/dev/null | fgrep -q inet_pton || exit 254
15
16trace_libc_inet_pton_backtrace() {
17	idx=0
18	expected[0]="ping[][0-9 \.:]+probe_libc:inet_pton: \([[:xdigit:]]+\)"
19	expected[1]=".*inet_pton[[:space:]]\($libc\)$"
20	case "$(uname -m)" in
21	s390x)
22		eventattr='call-graph=dwarf'
23		expected[2]="gaih_inet.*[[:space:]]\($libc|inlined\)$"
24		expected[3]="__GI_getaddrinfo[[:space:]]\($libc|inlined\)$"
25		expected[4]="main[[:space:]]\(.*/bin/ping.*\)$"
26		expected[5]="__libc_start_main[[:space:]]\($libc\)$"
27		expected[6]="_start[[:space:]]\(.*/bin/ping.*\)$"
28		;;
29	*)
30		eventattr='max-stack=3'
31		expected[2]="getaddrinfo[[:space:]]\($libc\)$"
32		expected[3]=".*\(.*/bin/ping.*\)$"
33		;;
34	esac
35
36	file=`mktemp -u /tmp/perf.data.XXX`
37
38	perf record -e probe_libc:inet_pton/$eventattr/ -o $file ping -6 -c 1 ::1 > /dev/null 2>&1
39	perf script -i $file | while read line ; do
40		echo $line
41		echo "$line" | egrep -q "${expected[$idx]}"
42		if [ $? -ne 0 ] ; then
43			printf "FAIL: expected backtrace entry %d \"%s\" got \"%s\"\n" $idx "${expected[$idx]}" "$line"
44			exit 1
45		fi
46		let idx+=1
47		[ -z "${expected[$idx]}" ] && break
48	done
49
50	rm -f $file
51}
52
53# Check for IPv6 interface existence
54ip a sh lo | fgrep -q inet6 || exit 2
55
56skip_if_no_perf_probe && \
57perf probe -q $libc inet_pton && \
58trace_libc_inet_pton_backtrace
59err=$?
60rm -f ${file}
61perf probe -q -d probe_libc:inet_pton
62exit $err
63