diff options
Diffstat (limited to 'scripts/check-local-export')
-rwxr-xr-x | scripts/check-local-export | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/scripts/check-local-export b/scripts/check-local-export new file mode 100755 index 000000000..f90b5a9c6 --- /dev/null +++ b/scripts/check-local-export @@ -0,0 +1,70 @@ +#!/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 $? |