2019-08-23 23:50:25 +00:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
|
|
if [ "$(uname -s)" = "FreeBSD" ]; then
|
|
|
|
echo "Not testing for shared object dependencies on FreeBSD."
|
|
|
|
exit 0
|
|
|
|
fi
|
|
|
|
|
|
|
|
rootdir=$(readlink -f $(dirname $0)/../..)
|
2020-05-07 21:38:50 +00:00
|
|
|
|
|
|
|
if [[ ! -f $1 ]]; then
|
|
|
|
echo "ERROR: SPDK test configuration not specified"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
source $1
|
2019-08-23 23:50:25 +00:00
|
|
|
source "$rootdir/test/common/autotest_common.sh"
|
|
|
|
|
|
|
|
libdir="$rootdir/build/lib"
|
|
|
|
libdeps_file="$rootdir/mk/spdk.lib_deps.mk"
|
2020-05-04 14:57:14 +00:00
|
|
|
source_abi_dir="$HOME/spdk_20_04/build/lib"
|
2020-04-07 01:16:52 +00:00
|
|
|
suppression_file="$HOME/abigail_suppressions.ini"
|
2020-02-28 23:14:52 +00:00
|
|
|
|
|
|
|
function confirm_abi_deps() {
|
2020-03-23 14:52:23 +00:00
|
|
|
local processed_so=0
|
|
|
|
|
2020-02-28 23:14:52 +00:00
|
|
|
if ! hash abidiff; then
|
|
|
|
echo "Unable to check ABI compatibility. Please install abidiff."
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ ! -d $source_abi_dir ]; then
|
|
|
|
echo "No source ABI available, failing this test."
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
2020-05-07 11:27:06 +00:00
|
|
|
cat << EOF > ${suppression_file}
|
2020-05-06 20:07:22 +00:00
|
|
|
[suppress_variable]
|
|
|
|
name = SPDK_LOG_IDXD
|
2020-05-06 20:12:56 +00:00
|
|
|
[suppress_variable]
|
|
|
|
name = SPDK_LOG_IOAT
|
2020-05-06 20:25:28 +00:00
|
|
|
[suppress_variable]
|
|
|
|
name = SPDK_LOG_JSON_UTIL
|
2020-05-06 20:52:16 +00:00
|
|
|
[suppress_variable]
|
|
|
|
name = SPDK_LOG_RPC
|
|
|
|
[suppress_variable]
|
|
|
|
name = SPDK_LOG_RPC_CLIENT
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_jsonrpc_server_handle_request
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_jsonrpc_server_handle_error
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_jsonrpc_server_send_response
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_jsonrpc_parse_request
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_jsonrpc_free_request
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_jsonrpc_parse_response
|
2020-05-06 22:17:17 +00:00
|
|
|
[suppress_variable]
|
|
|
|
name = SPDK_LOG_LOG_RPC
|
2020-05-06 22:13:57 +00:00
|
|
|
[suppress_variable]
|
|
|
|
name = SPDK_LOG_LOG
|
2020-05-07 17:06:34 +00:00
|
|
|
[suppress_variable]
|
|
|
|
name = SPDK_LOG_LVOL
|
2020-05-07 17:24:25 +00:00
|
|
|
[suppress_variable]
|
|
|
|
name = SPDK_LOG_NBD
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_nbd_disk_find_by_nbd_path
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_nbd_disk_first
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_nbd_disk_next
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_nbd_disk_get_nbd_path
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_nbd_disk_get_bdev_name
|
2020-05-07 17:35:13 +00:00
|
|
|
[suppress_variable]
|
|
|
|
name = SPDK_LOG_NET
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_interface_net_interface_add_ip_address
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_interface_net_interface_delete_ip_address
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_interface_get_list
|
2020-05-07 18:24:00 +00:00
|
|
|
[suppress_function]
|
|
|
|
name = spdk_get_uevent
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_uevent_connect
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_nvme_ctrlr_get_current_process
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_nvme_ctrlr_get_process
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_nvme_get_ctrlr_by_trid_unsafe
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_nvme_io_msg_process
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_nvme_wait_for_completion
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_nvme_wait_for_completion_robust_lock
|
|
|
|
[suppress_function]
|
|
|
|
name = spdk_nvme_wait_for_completion_timeout
|
|
|
|
[suppress_variable]
|
|
|
|
name = SPDK_LOG_NVME
|
|
|
|
[suppress_variable]
|
|
|
|
name = SPDK_LOG_OPAL
|
|
|
|
[suppress_variable]
|
|
|
|
name = spdk_opal_method
|
|
|
|
[suppress_variable]
|
|
|
|
name = spdk_opal_uid
|
2020-05-09 23:11:14 +00:00
|
|
|
[suppress_variable]
|
|
|
|
name = SPDK_LOG_REDUCE
|
2020-04-03 19:22:12 +00:00
|
|
|
EOF
|
2020-04-07 01:16:52 +00:00
|
|
|
|
2020-03-23 14:35:04 +00:00
|
|
|
for object in "$libdir"/libspdk_*.so; do
|
2020-02-28 23:14:52 +00:00
|
|
|
so_file=$(basename $object)
|
|
|
|
if [ ! -f "$source_abi_dir/$so_file" ]; then
|
|
|
|
echo "No corresponding object for $so_file in canonical directory. Skipping."
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
|
2020-04-07 01:16:52 +00:00
|
|
|
if ! abidiff $source_abi_dir/$so_file $libdir/$so_file --leaf-changes-only --suppressions $suppression_file --stat > /dev/null; then
|
2020-02-28 23:14:52 +00:00
|
|
|
found_abi_change=false
|
2020-04-07 01:16:52 +00:00
|
|
|
output=$(abidiff $source_abi_dir/$so_file $libdir/$so_file --leaf-changes-only --suppressions $suppression_file --stat) || true
|
2020-03-27 01:48:39 +00:00
|
|
|
new_so_maj=$(readlink $libdir/$so_file | awk -F'\\.so\\.' '{print $2}' | cut -d '.' -f1)
|
|
|
|
new_so_min=$(readlink $libdir/$so_file | awk -F'\\.so\\.' '{print $2}' | cut -d '.' -f2)
|
|
|
|
old_so_maj=$(readlink $source_abi_dir/$so_file | awk -F'\\.so\\.' '{print $2}' | cut -d '.' -f1)
|
|
|
|
old_so_min=$(readlink $source_abi_dir/$so_file | awk -F'\\.so\\.' '{print $2}' | cut -d '.' -f2)
|
2020-02-28 23:14:52 +00:00
|
|
|
so_name_changed=$(grep "ELF SONAME changed" <<< "$output") || so_name_changed="No"
|
|
|
|
function_summary=$(grep "functions summary" <<< "$output")
|
|
|
|
variable_summary=$(grep "variables summary" <<< "$output")
|
2020-04-07 01:16:52 +00:00
|
|
|
# remove any filtered out variables.
|
2020-05-07 21:03:12 +00:00
|
|
|
function_summary=$(sed "s/ [()][^)]*[)]//g" <<< "$function_summary")
|
2020-04-07 01:16:52 +00:00
|
|
|
variable_summary=$(sed "s/ [()][^)]*[)]//g" <<< "$variable_summary")
|
2020-02-28 23:14:52 +00:00
|
|
|
|
|
|
|
read -r _ _ _ removed_functions _ changed_functions _ added_functions _ <<< "$function_summary"
|
|
|
|
read -r _ _ _ removed_vars _ changed_vars _ added_vars _ <<< "$variable_summary"
|
|
|
|
|
|
|
|
if [ $removed_functions -ne 0 ] || [ $removed_vars -ne 0 ]; then
|
|
|
|
if [ "$new_so_maj" == "$old_so_maj" ]; then
|
|
|
|
touch $fail_file
|
|
|
|
echo "Please update the major SO version for $so_file. API functions or variables have been removed since last release."
|
|
|
|
fi
|
|
|
|
found_abi_change=true
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ $changed_functions -ne 0 ] || [ $changed_vars -ne 0 ]; then
|
|
|
|
if [ "$new_so_maj" == "$old_so_maj" ]; then
|
|
|
|
touch $fail_file
|
|
|
|
echo "Please update the major SO version for $so_file. API functions or variables have been changed since last release."
|
|
|
|
fi
|
|
|
|
found_abi_change=true
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ $added_functions -ne 0 ] || [ $added_vars -ne 0 ]; then
|
|
|
|
if [ "$new_so_min" == "$old_so_min" ] && [ "$new_so_maj" == "$old_so_maj" ] && ! $found_abi_change; then
|
|
|
|
touch $fail_file
|
|
|
|
echo "Please update the minor SO version for $so_file. API functions or variables have been added since last release."
|
|
|
|
fi
|
|
|
|
found_abi_change=true
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ "$so_name_changed" != "No" ]; then
|
|
|
|
if ! $found_abi_change; then
|
2020-05-06 20:07:22 +00:00
|
|
|
# Unfortunately, libspdk_idxd made it into 20.04 without an SO suffix. TODO:: remove after 20.07
|
|
|
|
if [ "$so_file" != "libspdk_idxd.so" ]; then
|
|
|
|
echo "SO name for $so_file changed without a change to abi. please revert that change."
|
|
|
|
touch $fail_file
|
|
|
|
fi
|
2020-02-28 23:14:52 +00:00
|
|
|
fi
|
2020-04-07 01:16:52 +00:00
|
|
|
|
2020-05-07 11:27:06 +00:00
|
|
|
if [ "$new_so_maj" != "$old_so_maj" ] && [ "$new_so_min" != "0" ]; then
|
2020-04-07 01:16:52 +00:00
|
|
|
echo "SO major version for $so_file was bumped. Please reset the minor version to 0."
|
|
|
|
touch $fail_file
|
|
|
|
fi
|
2020-02-28 23:14:52 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
continue
|
|
|
|
fi
|
2020-05-07 11:27:06 +00:00
|
|
|
processed_so=$((processed_so + 1))
|
2020-02-28 23:14:52 +00:00
|
|
|
done
|
2020-04-07 01:16:52 +00:00
|
|
|
rm -f $suppression_file
|
2020-03-23 14:52:23 +00:00
|
|
|
echo "Processed $processed_so objects."
|
2020-02-28 23:14:52 +00:00
|
|
|
}
|
2019-08-23 23:50:25 +00:00
|
|
|
|
|
|
|
# This function is needed to properly evaluate the Make variables into actual dependencies.
|
|
|
|
function replace_defined_variables() {
|
|
|
|
local arr=("$@")
|
|
|
|
local bad_values=()
|
|
|
|
local good_values=()
|
|
|
|
local new_values
|
|
|
|
for dep in "${arr[@]}"; do
|
|
|
|
if [[ $dep == *'$'* ]]; then
|
|
|
|
raw_dep=${dep/$\(/}
|
|
|
|
raw_dep=${raw_dep/\)/ }
|
|
|
|
bad_values+=("$raw_dep")
|
|
|
|
else
|
|
|
|
good_values+=("$dep")
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
for dep in "${bad_values[@]}"; do
|
2020-01-14 12:03:17 +00:00
|
|
|
dep_def_arr=($(grep -v "#" $libdeps_file | grep "${dep}" | cut -d "=" -f 2 | xargs))
|
2019-08-23 23:50:25 +00:00
|
|
|
new_values=($(replace_defined_variables "${dep_def_arr[@]}"))
|
2020-05-07 11:27:06 +00:00
|
|
|
good_values=("${good_values[@]}" "${new_values[@]}")
|
2019-08-23 23:50:25 +00:00
|
|
|
done
|
|
|
|
echo ${good_values[*]}
|
|
|
|
}
|
|
|
|
|
|
|
|
function confirm_deps() {
|
|
|
|
lib=$1
|
|
|
|
missing_syms=()
|
|
|
|
dep_names=()
|
|
|
|
found_symbol_lib=""
|
|
|
|
|
|
|
|
#keep the space here to differentiate bdev and bdev_*
|
|
|
|
lib_shortname=$(basename $lib | sed 's,libspdk_,,g' | sed 's,\.so, ,g')
|
2020-01-14 12:03:17 +00:00
|
|
|
lib_make_deps=($(grep "DEPDIRS-${lib_shortname}" $libdeps_file | cut -d "=" -f 2 | xargs))
|
2019-08-23 23:50:25 +00:00
|
|
|
lib_make_deps=($(replace_defined_variables "${lib_make_deps[@]}"))
|
|
|
|
|
2019-09-06 16:36:26 +00:00
|
|
|
for ign_dep in "${IGNORED_LIBS[@]}"; do
|
|
|
|
for i in "${!lib_make_deps[@]}"; do
|
|
|
|
if [[ ${lib_make_deps[i]} == "$ign_dep" ]]; then
|
|
|
|
unset 'lib_make_deps[i]'
|
|
|
|
fi
|
|
|
|
done
|
2019-08-23 23:50:25 +00:00
|
|
|
done
|
|
|
|
|
|
|
|
symbols=$(readelf -s $lib | grep -E "NOTYPE.*GLOBAL.*UND" | awk '{print $8}' | sort | uniq)
|
|
|
|
for symbol in $symbols; do
|
|
|
|
for deplib in $DEP_LIBS; do
|
|
|
|
if [ "$deplib" == "$lib" ]; then
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
found_symbol=$(readelf -s $deplib | grep -E "DEFAULT\s+[0-9]+\s$symbol$") || true
|
|
|
|
if [ "$found_symbol" != "" ]; then
|
|
|
|
found_symbol_lib=$(basename $deplib | sed 's,libspdk_,,g' | sed 's,\.so,,g')
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
if [ "$found_symbol" == "" ]; then
|
|
|
|
missing_syms+=("$symbol")
|
|
|
|
else
|
|
|
|
dep_names+=("$found_symbol_lib")
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
IFS=$'\n'
|
|
|
|
# Ignore any event_* dependencies. Those are based on the subsystem configuration and not readelf.
|
2020-05-07 11:27:06 +00:00
|
|
|
lib_make_deps=($(printf "%s\n" "${lib_make_deps[@]}" | sort | grep -v "event_"))
|
2019-08-23 23:50:25 +00:00
|
|
|
# Ignore the env_dpdk readelf dependency. We don't want people explicitly linking against it.
|
2020-05-07 11:27:06 +00:00
|
|
|
dep_names=($(printf "%s\n" "${dep_names[@]}" | sort | uniq | grep -v "env_dpdk"))
|
2019-08-23 23:50:25 +00:00
|
|
|
unset IFS
|
2019-11-25 11:21:54 +00:00
|
|
|
diff=$(echo "${dep_names[@]}" "${lib_make_deps[@]}" | tr ' ' '\n' | sort | uniq -u)
|
2019-08-23 23:50:25 +00:00
|
|
|
if [ "$diff" != "" ]; then
|
|
|
|
touch $fail_file
|
|
|
|
echo "there was a dependency mismatch in the library $lib_shortname"
|
|
|
|
echo "The makefile lists: '${lib_make_deps[*]}'"
|
|
|
|
echo "readelf outputs : '${dep_names[*]}'"
|
|
|
|
echo "---------------------------------------------------------------------"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
# By removing the spdk.lib_deps.mk file from spdk.lib.mk, we ensure that we won't
|
|
|
|
# create any link dependencies. Then we can be sure we get a valid accounting of the
|
|
|
|
# symbol dependencies we have.
|
|
|
|
sed -i -e 's,include $(SPDK_ROOT_DIR)/mk/spdk.lib_deps.mk,,g' "$rootdir/mk/spdk.lib.mk"
|
|
|
|
|
2020-05-07 21:38:50 +00:00
|
|
|
source ~/autorun-spdk.conf
|
2020-04-09 17:54:24 +00:00
|
|
|
config_params=$(get_config_params)
|
2019-08-23 23:50:25 +00:00
|
|
|
if [ "$SPDK_TEST_OCF" -eq 1 ]; then
|
|
|
|
config_params="$config_params --with-ocf=$rootdir/build/ocf.a"
|
|
|
|
fi
|
|
|
|
|
2019-12-19 15:57:30 +00:00
|
|
|
$MAKE $MAKEFLAGS clean
|
2019-08-23 23:50:25 +00:00
|
|
|
./configure $config_params --with-shared
|
|
|
|
$MAKE $MAKEFLAGS
|
|
|
|
|
|
|
|
xtrace_disable
|
|
|
|
|
2020-02-28 23:14:52 +00:00
|
|
|
fail_file=$output_dir/check_so_deps_fail
|
|
|
|
|
|
|
|
rm -f $fail_file
|
|
|
|
|
|
|
|
run_test "confirm_abi_deps" confirm_abi_deps
|
|
|
|
|
2019-08-23 23:50:25 +00:00
|
|
|
echo "---------------------------------------------------------------------"
|
|
|
|
# Exclude libspdk_env_dpdk.so from the library list. We don't link against this one so that
|
|
|
|
# users can define their own environment abstraction. However we do want to still check it
|
|
|
|
# for dependencies to avoid printing out a bunch of confusing symbols under the missing
|
|
|
|
# symbols section.
|
|
|
|
SPDK_LIBS=$(ls -1 $libdir/libspdk_*.so | grep -v libspdk_env_dpdk.so)
|
|
|
|
DEP_LIBS=$(ls -1 $libdir/libspdk_*.so)
|
|
|
|
|
2019-09-06 16:36:26 +00:00
|
|
|
IGNORED_LIBS=()
|
|
|
|
if grep -q 'CONFIG_VHOST_INTERNAL_LIB?=n' $rootdir/mk/config.mk; then
|
|
|
|
IGNORED_LIBS+=("rte_vhost")
|
|
|
|
fi
|
|
|
|
|
2020-05-07 11:27:06 +00:00
|
|
|
(
|
|
|
|
for lib in $SPDK_LIBS; do confirm_deps $lib & done
|
|
|
|
wait
|
|
|
|
)
|
2019-08-23 23:50:25 +00:00
|
|
|
|
|
|
|
$MAKE $MAKEFLAGS clean
|
|
|
|
git checkout "$rootdir/mk/spdk.lib.mk"
|
|
|
|
|
|
|
|
if [ -f $fail_file ]; then
|
|
|
|
rm -f $fail_file
|
|
|
|
echo "shared object test failed"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
xtrace_restore
|