aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/check-local-export
blob: da745e2743b74dfd6da62a943ceef6b73bbf8044 (plain) (blame)
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
#!/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}