Staging
v0.5.1
https://github.com/torvalds/linux
Raw File
Tip revision: f2906aa863381afb0015a9eb7fefad885d4e5a56 authored by Linus Torvalds on 06 June 2022, 00:18:54 UTC
Linux 5.19-rc1
Tip revision: f2906aa
check-local-export
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (C) 2022 Masahiro Yamada <masahiroy@kernel.org>
#
# Exit with error if a local exported symbol is found.
# EXPORT_SYMBOL should be used for global symbols.

set -e

declare -A symbol_types
declare -a export_symbols

exit_code=0

while read value type name
do
	# Skip the line if the number of fields is less than 3.
	#
	# case 1)
	#   For undefined symbols, the first field (value) is empty.
	#   The outout looks like this:
	#     "                 U _printk"
	#   It is unneeded to record undefined symbols.
	#
	# case 2)
	#   For Clang LTO, llvm-nm outputs a line with type 't' but empty name:
	#     "---------------- t"
	if [[ -z ${name} ]]; then
		continue
	fi

	# save (name, type) in the associative array
	symbol_types[${name}]=${type}

	# append the exported symbol to the array
	if [[ ${name} == __ksymtab_* ]]; then
		export_symbols+=(${name#__ksymtab_})
	fi

	# If there is no symbol in the object, ${NM} (both GNU nm and llvm-nm)
	# shows 'no symbols' diagnostic (but exits with 0). It is harmless and
	# hidden by '2>/dev/null'. However, it suppresses real error messages
	# as well. Add a hand-crafted error message here.
	#
	# Use --quiet instead of 2>/dev/null when we upgrade the minimum version
	# of binutils to 2.37, llvm to 13.0.0.
	#
	# Then, the following line will be really simple:
	#   done < <(${NM} --quiet ${1})
done < <(${NM} ${1} 2>/dev/null || { echo "${0}: ${NM} failed" >&2; false; } )

# Catch error in the process substitution
wait $!

for name in "${export_symbols[@]}"
do
	# nm(3) says "If lowercase, the symbol is usually local"
	if [[ ${symbol_types[$name]} =~ [a-z] ]]; then
		echo "$@: error: local symbol '${name}' was exported" >&2
		exit_code=1
	fi
done

exit ${exit_code}
back to top