Commit | Line | Data |
---|---|---|
033a52d0 | 1 | #!/bin/sh |
31cb50b5 MY |
2 | # SPDX-License-Identifier: GPL-2.0-only |
3 | # | |
4 | # Copyright (C) 2022 Masahiro Yamada <masahiroy@kernel.org> | |
033a52d0 | 5 | # Copyright (C) 2022 Owen Rafferty <owen@owenrafferty.com> |
31cb50b5 MY |
6 | # |
7 | # Exit with error if a local exported symbol is found. | |
8 | # EXPORT_SYMBOL should be used for global symbols. | |
9 | ||
10 | set -e | |
033a52d0 | 11 | pid=$$ |
31cb50b5 | 12 | |
da4288b9 MY |
13 | # If there is no symbol in the object, ${NM} (both GNU nm and llvm-nm) shows |
14 | # 'no symbols' diagnostic (but exits with 0). It is harmless and hidden by | |
15 | # '2>/dev/null'. However, it suppresses real error messages as well. Add a | |
16 | # hand-crafted error message here. | |
17 | # | |
18 | # TODO: | |
19 | # Use --quiet instead of 2>/dev/null when we upgrade the minimum version of | |
20 | # binutils to 2.37, llvm to 13.0.0. | |
033a52d0 OR |
21 | # Then, the following line will be simpler: |
22 | # { ${NM} --quiet ${1} || kill 0; } | | |
23 | ||
24 | { ${NM} ${1} 2>/dev/null || { echo "${0}: ${NM} failed" >&2; kill $pid; } } | | |
25 | ${AWK} -v "file=${1}" ' | |
26 | BEGIN { | |
27 | i = 0 | |
28 | } | |
29 | ||
30 | # Skip the line if the number of fields is less than 3. | |
31 | # | |
32 | # case 1) | |
33 | # For undefined symbols, the first field (value) is empty. | |
34 | # The outout looks like this: | |
35 | # " U _printk" | |
36 | # It is unneeded to record undefined symbols. | |
37 | # | |
38 | # case 2) | |
39 | # For Clang LTO, llvm-nm outputs a line with type t but empty name: | |
40 | # "---------------- t" | |
41 | !length($3) { | |
42 | next | |
43 | } | |
da4288b9 | 44 | |
033a52d0 OR |
45 | # save (name, type) in the associative array |
46 | { symbol_types[$3]=$2 } | |
31cb50b5 | 47 | |
033a52d0 OR |
48 | # append the exported symbol to the array |
49 | ($3 ~ /^__ksymtab_/) { | |
50 | export_symbols[i] = $3 | |
51 | sub(/^__ksymtab_/, "", export_symbols[i]) | |
52 | i++ | |
53 | } | |
31cb50b5 | 54 | |
033a52d0 OR |
55 | END { |
56 | exit_code = 0 | |
57 | for (j = 0; j < i; ++j) { | |
58 | name = export_symbols[j] | |
59 | # nm(3) says "If lowercase, the symbol is usually local" | |
60 | if (symbol_types[name] ~ /[a-z]/) { | |
61 | printf "%s: error: local symbol %s was exported\n", | |
62 | file, name | "cat 1>&2" | |
63 | exit_code = 1 | |
64 | } | |
65 | } | |
31cb50b5 | 66 | |
033a52d0 OR |
67 | exit exit_code |
68 | }' | |
31cb50b5 | 69 | |
033a52d0 | 70 | exit $? |