| #!/bin/sh | 
 | # SPDX-License-Identifier: GPL-2.0-only | 
 | # | 
 | # Copyright (C) 2022 Masahiro Yamada <masahiroy@kernel.org> | 
 | # Copyright (C) 2022 Owen Rafferty <owen@owenrafferty.com> | 
 | # | 
 | # Exit with error if a local exported symbol is found. | 
 | # EXPORT_SYMBOL should be used for global symbols. | 
 |  | 
 | set -e | 
 | pid=$$ | 
 |  | 
 | # 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 simpler: | 
 | #   { ${NM} --quiet ${1} || kill 0; } | | 
 |  | 
 | { ${NM} ${1} 2>/dev/null || { echo "${0}: ${NM} failed" >&2; kill $pid; } } | | 
 | ${AWK} -v "file=${1}" ' | 
 | BEGIN { | 
 | 	i = 0 | 
 | } | 
 |  | 
 | # 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" | 
 | !length($3) { | 
 | 	next | 
 | } | 
 |  | 
 | # save (name, type) in the associative array | 
 | { symbol_types[$3]=$2 } | 
 |  | 
 | # append the exported symbol to the array | 
 | ($3 ~ /^__ksymtab_/) { | 
 | 	export_symbols[i] = $3 | 
 | 	sub(/^__ksymtab_/, "", export_symbols[i]) | 
 | 	i++ | 
 | } | 
 |  | 
 | END { | 
 | 	exit_code = 0 | 
 | 	for (j = 0; j < i; ++j) { | 
 | 		name = export_symbols[j] | 
 | 		# nm(3) says "If lowercase, the symbol is usually local" | 
 | 		if (symbol_types[name] ~ /[a-z]/) { | 
 | 			printf "%s: error: local symbol %s was exported\n", | 
 | 				file, name | "cat 1>&2" | 
 | 			exit_code = 1 | 
 | 		} | 
 | 	} | 
 |  | 
 | 	exit exit_code | 
 | }' | 
 |  | 
 | exit $? |