1#!/bin/bash
2
3# Copyright (C) 2021 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#       http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17# Usage:
18#   development/gki/kmi_abi_chk/kmi_static_chk.sh \
19#     <current_symbol_info> <previous_symbol_info> (abi_symbollist.report)
20#
21#   abi_symbollist.report is from the previous/old GKI and optional.
22#   If it's not on the command line, all symbols from the previous/old GKI
23#   are considered KMI and will be checked.
24if [[ "$#" -lt 2 ]]; then
25  echo "Usage: $0 <current_symbol_info> <previous_symbol_info> (abi_symbollist.report)"
26  exit 1
27fi
28
29ret=0
30for f in $1 $2; do
31  if [[ ! -e "$f" ]]; then
32    echo "Kernel symbol file $f does not exist!" >&2
33    ret=1
34  elif ! grep -iE "^0x[0-9a-f]{8}+.[_0-9a-z]+.vmlinux.EXPORT_SYMBOL" $f > /dev/null; then
35    ret=1
36    echo "$f doesn't look like kernel symbol file!" >&2
37  fi
38done
39
40unset abi_list
41if [[ "$#" -gt 2 ]]; then
42  if [[ ! -e "$3" ]]; then
43    echo "ABI symbol list $3 does not exist!" >&2
44    ret=1
45  else
46    abi_list=$3
47  fi
48fi
49
50if [[ ! ret -eq 0 ]]; then
51  exit $ret
52fi
53
54tmp_symvers_new=$(mktemp /tmp/linux-symvers.XXXXXX)
55tmp_symvers_old=$(mktemp /tmp/linux-symvers.XXXXXX)
56tmp_abi_lst_old=$(mktemp /tmp/linux-symvers.XXXXXX)
57
58trap "rm -f $tmp_symvers_new tmp_symvers_old tmp_abi_lst_old" EXIT
59
60curr=$1
61shift
62
63# Filter for vmlinux EXPORTE_SYMBOL* and remove trailing white spaces.
64# The reason trailing white spaces is removed only for the current
65# symbol file is because the following example/possibility:
66#
67# In the current symbol file:
68# 0x8581ad8e	get_net_ns_by_fd	vmlinux	EXPORT_SYMBOL\t
69#
70# In the previous symbol file:
71# 0x8581ad8e	get_net_ns_by_fd	vmlinux	EXPORT_SYMBOL_GPL\t
72#
73# The symbol is GPLed previously, but not in the current release, which won't
74# break KMI ABI, because the requirement is "relaxed". We want this case to
75# pass so a keyword like "...EXPORT_SYMBOL" in the current symbol file can
76# still match "...EXPORT_SYMBOL_GPL" in the previous symbol file.
77grep "EXPORT_SYMBOL" $curr | sed 's/[ \t]*$//' > $tmp_symvers_new
78
79if [[ -v abi_list ]]; then
80  awk '{print $1}' $abi_list > $tmp_abi_lst_old
81  echo "ABI list: $abi_list"
82fi
83
84echo "Current kernel symbol file, $curr, is checking against:"
85
86for f in $1; do
87  if [[ -v abi_list ]]; then
88    grep -wf $tmp_abi_lst_old $f > $tmp_symvers_old
89  else
90    cp $f $tmp_symvers_old
91  fi
92
93  echo "	$f"
94# if nothing is found, grep returns 1, which means every symbol in the
95# previous release (usually in *.symvers-$BID) can be found in the current
96# release, so is considered successful here.
97# if grep returns 0, which means some symbols are found in the previous
98# symbol file but not in the current symbol file, then something wrong!
99  if grep -vf $tmp_symvers_new $tmp_symvers_old; then
100    ret=1
101    echo "$f contains symbol(s) not found in, or incompatible with, $curr." >&2
102  fi
103done
104
105exit $ret
106