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

# catch errors from ${NM}
set -o pipefail

# Run the last element of a pipeline in the current shell.
# Without this, the while-loop would be executed in a subshell, and
# the changes made to 'symbol_types' and 'export_symbols' would be lost.
shopt -s lastpipe

declare -A symbol_types
declare -a export_symbols

exit_code=0

# 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.
#
# TODO:
# 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:
#   ${NM} --quiet ${1} |

{ ${NM} ${1} 2>/dev/null || { echo "${0}: ${NM} failed" >&2; false; } } |
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
done

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}