1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
#!/bin/sh
# build id cache operations
# SPDX-License-Identifier: GPL-2.0
# skip if there's no readelf
if ! [ -x "$(command -v readelf)" ]; then
echo "failed: no readelf, install binutils"
exit 2
fi
# skip if there's no compiler
if ! [ -x "$(command -v cc)" ]; then
echo "failed: no compiler, install gcc"
exit 2
fi
# check what we need to test windows binaries
add_pe=1
run_pe=1
if ! perf version --build-options | grep -q 'libbfd: .* on '; then
echo "WARNING: perf not built with libbfd. PE binaries will not be tested."
add_pe=0
run_pe=0
fi
if ! which wine > /dev/null; then
echo "WARNING: wine not found. PE binaries will not be run."
run_pe=0
fi
# set up wine
if [ ${run_pe} -eq 1 ]; then
wineprefix=$(mktemp -d /tmp/perf.wineprefix.XXX)
export WINEPREFIX=${wineprefix}
# clear display variables to prevent wine from popping up dialogs
unset DISPLAY
unset WAYLAND_DISPLAY
fi
ex_md5=$(mktemp /tmp/perf.ex.MD5.XXX)
ex_sha1=$(mktemp /tmp/perf.ex.SHA1.XXX)
ex_pe=$(dirname $0)/../pe-file.exe
echo 'int main(void) { return 0; }' | cc -Wl,--build-id=sha1 -o ${ex_sha1} -x c -
echo 'int main(void) { return 0; }' | cc -Wl,--build-id=md5 -o ${ex_md5} -x c -
echo "test binaries: ${ex_sha1} ${ex_md5} ${ex_pe}"
check()
{
case $1 in
*.exe)
# We don't have a tool that can pull a nicely formatted build-id out of
# a PE file, but we can extract the whole section with objcopy and
# format it ourselves. The .buildid section is a Debug Directory
# containing a CodeView entry:
# https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#debug-directory-image-only
# https://github.com/dotnet/runtime/blob/da94c022576a5c3bbc0e896f006565905eb137f9/docs/design/specs/PE-COFF.md
# The build-id starts at byte 33 and must be rearranged into a GUID.
id=`objcopy -O binary --only-section=.buildid $1 /dev/stdout | \
cut -c 33-48 | hexdump -ve '/1 "%02x"' | \
sed 's@^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(.*\)0a$@\4\3\2\1\6\5\8\7\9@'`
;;
*)
id=`readelf -n ${1} 2>/dev/null | grep 'Build ID' | awk '{print $3}'`
;;
esac
echo "build id: ${id}"
link=${build_id_dir}/.build-id/${id:0:2}/${id:2}
echo "link: ${link}"
if [ ! -h $link ]; then
echo "failed: link ${link} does not exist"
exit 1
fi
file=${build_id_dir}/.build-id/${id:0:2}/`readlink ${link}`/elf
echo "file: ${file}"
if [ ! -x $file ]; then
echo "failed: file ${file} does not exist"
exit 1
fi
diff ${file} ${1}
if [ $? -ne 0 ]; then
echo "failed: ${file} do not match"
exit 1
fi
${perf} buildid-cache -l | grep ${id}
if [ $? -ne 0 ]; then
echo "failed: ${id} is not reported by \"perf buildid-cache -l\""
exit 1
fi
echo "OK for ${1}"
}
test_add()
{
build_id_dir=$(mktemp -d /tmp/perf.debug.XXX)
perf="perf --buildid-dir ${build_id_dir}"
${perf} buildid-cache -v -a ${1}
if [ $? -ne 0 ]; then
echo "failed: add ${1} to build id cache"
exit 1
fi
check ${1}
rm -rf ${build_id_dir}
}
test_record()
{
data=$(mktemp /tmp/perf.data.XXX)
build_id_dir=$(mktemp -d /tmp/perf.debug.XXX)
log=$(mktemp /tmp/perf.log.XXX)
perf="perf --buildid-dir ${build_id_dir}"
echo "running: perf record $@"
${perf} record --buildid-all -o ${data} $@ &> ${log}
if [ $? -ne 0 ]; then
echo "failed: record $@"
echo "see log: ${log}"
exit 1
fi
check ${@: -1}
rm -f ${log}
rm -rf ${build_id_dir}
rm -rf ${data}
}
# add binaries manual via perf buildid-cache -a
test_add ${ex_sha1}
test_add ${ex_md5}
if [ ${add_pe} -eq 1 ]; then
test_add ${ex_pe}
fi
# add binaries via perf record post processing
test_record ${ex_sha1}
test_record ${ex_md5}
if [ ${run_pe} -eq 1 ]; then
test_record wine ${ex_pe}
fi
# cleanup
rm ${ex_sha1} ${ex_md5}
if [ ${run_pe} -eq 1 ]; then
rm -r ${wineprefix}
fi
exit ${err}
|