162306a36Sopenharmony_ci#!/bin/sh
262306a36Sopenharmony_ci# build id cache operations
362306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci# skip if there's no readelf
662306a36Sopenharmony_ciif ! [ -x "$(command -v readelf)" ]; then
762306a36Sopenharmony_ci	echo "failed: no readelf, install binutils"
862306a36Sopenharmony_ci	exit 2
962306a36Sopenharmony_cifi
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci# skip if there's no compiler
1262306a36Sopenharmony_ciif ! [ -x "$(command -v cc)" ]; then
1362306a36Sopenharmony_ci	echo "failed: no compiler, install gcc"
1462306a36Sopenharmony_ci	exit 2
1562306a36Sopenharmony_cifi
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci# check what we need to test windows binaries
1862306a36Sopenharmony_ciadd_pe=1
1962306a36Sopenharmony_cirun_pe=1
2062306a36Sopenharmony_ciif ! perf version --build-options | grep -q 'libbfd: .* on '; then
2162306a36Sopenharmony_ci	echo "WARNING: perf not built with libbfd. PE binaries will not be tested."
2262306a36Sopenharmony_ci	add_pe=0
2362306a36Sopenharmony_ci	run_pe=0
2462306a36Sopenharmony_cifi
2562306a36Sopenharmony_ciif ! which wine > /dev/null; then
2662306a36Sopenharmony_ci	echo "WARNING: wine not found. PE binaries will not be run."
2762306a36Sopenharmony_ci	run_pe=0
2862306a36Sopenharmony_cifi
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci# set up wine
3162306a36Sopenharmony_ciif [ ${run_pe} -eq 1 ]; then
3262306a36Sopenharmony_ci	wineprefix=$(mktemp -d /tmp/perf.wineprefix.XXX)
3362306a36Sopenharmony_ci	export WINEPREFIX=${wineprefix}
3462306a36Sopenharmony_ci	# clear display variables to prevent wine from popping up dialogs
3562306a36Sopenharmony_ci	unset DISPLAY
3662306a36Sopenharmony_ci	unset WAYLAND_DISPLAY
3762306a36Sopenharmony_cifi
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ciex_md5=$(mktemp /tmp/perf.ex.MD5.XXX)
4062306a36Sopenharmony_ciex_sha1=$(mktemp /tmp/perf.ex.SHA1.XXX)
4162306a36Sopenharmony_ciex_pe=$(dirname $0)/../pe-file.exe
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ciecho 'int main(void) { return 0; }' | cc -Wl,--build-id=sha1 -o ${ex_sha1} -x c -
4462306a36Sopenharmony_ciecho 'int main(void) { return 0; }' | cc -Wl,--build-id=md5 -o ${ex_md5} -x c -
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ciecho "test binaries: ${ex_sha1} ${ex_md5} ${ex_pe}"
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cicheck()
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	case $1 in
5162306a36Sopenharmony_ci	*.exe)
5262306a36Sopenharmony_ci		# We don't have a tool that can pull a nicely formatted build-id out of
5362306a36Sopenharmony_ci		# a PE file, but we can extract the whole section with objcopy and
5462306a36Sopenharmony_ci		# format it ourselves. The .buildid section is a Debug Directory
5562306a36Sopenharmony_ci		# containing a CodeView entry:
5662306a36Sopenharmony_ci		#     https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#debug-directory-image-only
5762306a36Sopenharmony_ci		#     https://github.com/dotnet/runtime/blob/da94c022576a5c3bbc0e896f006565905eb137f9/docs/design/specs/PE-COFF.md
5862306a36Sopenharmony_ci		# The build-id starts at byte 33 and must be rearranged into a GUID.
5962306a36Sopenharmony_ci		id=`objcopy -O binary --only-section=.buildid $1 /dev/stdout | \
6062306a36Sopenharmony_ci			cut -c 33-48 | hexdump -ve '/1 "%02x"' | \
6162306a36Sopenharmony_ci			sed 's@^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(.*\)0a$@\4\3\2\1\6\5\8\7\9@'`
6262306a36Sopenharmony_ci		;;
6362306a36Sopenharmony_ci	*)
6462306a36Sopenharmony_ci		id=`readelf -n ${1} 2>/dev/null | grep 'Build ID' | awk '{print $3}'`
6562306a36Sopenharmony_ci		;;
6662306a36Sopenharmony_ci	esac
6762306a36Sopenharmony_ci	echo "build id: ${id}"
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	id_file=${id#??}
7062306a36Sopenharmony_ci	id_dir=${id%$id_file}
7162306a36Sopenharmony_ci	link=$build_id_dir/.build-id/$id_dir/$id_file
7262306a36Sopenharmony_ci	echo "link: ${link}"
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	if [ ! -h $link ]; then
7562306a36Sopenharmony_ci		echo "failed: link ${link} does not exist"
7662306a36Sopenharmony_ci		exit 1
7762306a36Sopenharmony_ci	fi
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	file=${build_id_dir}/.build-id/$id_dir/`readlink ${link}`/elf
8062306a36Sopenharmony_ci	echo "file: ${file}"
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	# Check for file permission of original file
8362306a36Sopenharmony_ci	# in case of pe-file.exe file
8462306a36Sopenharmony_ci	echo $1 | grep ".exe"
8562306a36Sopenharmony_ci	if [ $? -eq 0 ]; then
8662306a36Sopenharmony_ci		if [ -x $1 ] && [ ! -x $file ]; then
8762306a36Sopenharmony_ci			echo "failed: file ${file} executable does not exist"
8862306a36Sopenharmony_ci			exit 1
8962306a36Sopenharmony_ci		fi
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci		if [ ! -x $file ] && [ ! -e $file ]; then
9262306a36Sopenharmony_ci			echo "failed: file ${file} does not exist"
9362306a36Sopenharmony_ci			exit 1
9462306a36Sopenharmony_ci		fi
9562306a36Sopenharmony_ci	elif [ ! -x $file ]; then
9662306a36Sopenharmony_ci		echo "failed: file ${file} does not exist"
9762306a36Sopenharmony_ci		exit 1
9862306a36Sopenharmony_ci	fi
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	diff ${file} ${1}
10162306a36Sopenharmony_ci	if [ $? -ne 0 ]; then
10262306a36Sopenharmony_ci		echo "failed: ${file} do not match"
10362306a36Sopenharmony_ci		exit 1
10462306a36Sopenharmony_ci	fi
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	${perf} buildid-cache -l | grep ${id}
10762306a36Sopenharmony_ci	if [ $? -ne 0 ]; then
10862306a36Sopenharmony_ci		echo "failed: ${id} is not reported by \"perf buildid-cache -l\""
10962306a36Sopenharmony_ci		exit 1
11062306a36Sopenharmony_ci	fi
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	echo "OK for ${1}"
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_citest_add()
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	build_id_dir=$(mktemp -d /tmp/perf.debug.XXX)
11862306a36Sopenharmony_ci	perf="perf --buildid-dir ${build_id_dir}"
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	${perf} buildid-cache -v -a ${1}
12162306a36Sopenharmony_ci	if [ $? -ne 0 ]; then
12262306a36Sopenharmony_ci		echo "failed: add ${1} to build id cache"
12362306a36Sopenharmony_ci		exit 1
12462306a36Sopenharmony_ci	fi
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	check ${1}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	rm -rf ${build_id_dir}
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_citest_record()
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	data=$(mktemp /tmp/perf.data.XXX)
13462306a36Sopenharmony_ci	build_id_dir=$(mktemp -d /tmp/perf.debug.XXX)
13562306a36Sopenharmony_ci	log_out=$(mktemp /tmp/perf.log.out.XXX)
13662306a36Sopenharmony_ci	log_err=$(mktemp /tmp/perf.log.err.XXX)
13762306a36Sopenharmony_ci	perf="perf --buildid-dir ${build_id_dir}"
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	echo "running: perf record $*"
14062306a36Sopenharmony_ci	${perf} record --buildid-all -o ${data} "$@" 1>${log_out} 2>${log_err}
14162306a36Sopenharmony_ci	if [ $? -ne 0 ]; then
14262306a36Sopenharmony_ci		echo "failed: record $*"
14362306a36Sopenharmony_ci		echo "see log: ${log_err}"
14462306a36Sopenharmony_ci		exit 1
14562306a36Sopenharmony_ci	fi
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	args="$*"
14862306a36Sopenharmony_ci	check ${args##* }
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	rm -f ${log_out} ${log_err}
15162306a36Sopenharmony_ci	rm -rf ${build_id_dir}
15262306a36Sopenharmony_ci	rm -rf ${data}
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci# add binaries manual via perf buildid-cache -a
15662306a36Sopenharmony_citest_add ${ex_sha1}
15762306a36Sopenharmony_citest_add ${ex_md5}
15862306a36Sopenharmony_ciif [ ${add_pe} -eq 1 ]; then
15962306a36Sopenharmony_ci	test_add ${ex_pe}
16062306a36Sopenharmony_cifi
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci# add binaries via perf record post processing
16362306a36Sopenharmony_citest_record ${ex_sha1}
16462306a36Sopenharmony_citest_record ${ex_md5}
16562306a36Sopenharmony_ciif [ ${run_pe} -eq 1 ]; then
16662306a36Sopenharmony_ci	test_record wine ${ex_pe}
16762306a36Sopenharmony_cifi
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci# cleanup
17062306a36Sopenharmony_cirm ${ex_sha1} ${ex_md5}
17162306a36Sopenharmony_ciif [ ${run_pe} -eq 1 ]; then
17262306a36Sopenharmony_ci	rm -r ${wineprefix}
17362306a36Sopenharmony_cifi
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ciexit 0
176