xref: /dpdk/devtools/check-symbol-change.sh (revision 7be78d027918dbc846e502780faf94d5acdf5f75)
1#!/bin/sh
2# SPDX-License-Identifier: BSD-3-Clause
3# Copyright(c) 2018 Neil Horman <nhorman@tuxdriver.com>
4
5build_map_changes()
6{
7	local fname="$1"
8	local mapdb="$2"
9
10	cat "$fname" | awk '
11		# Initialize our variables
12		BEGIN {map="";sym="";ar="";sec=""; in_sec=0; in_map=0}
13
14		# Anything that starts with + or -, followed by an a
15		# and ends in the string .map is the name of our map file
16		# This may appear multiple times in a patch if multiple
17		# map files are altered, and all section/symbol names
18		# appearing between a triggering of this rule and the
19		# next trigger of this rule are associated with this file
20		/[-+] [ab]\/.*\.map/ {map=$2; in_map=1; next}
21
22		# The previous rule catches all .map files, anything else
23		# indicates we left the map chunk.
24		/[-+] [ab]\// {in_map=0}
25
26		# Triggering this rule, which starts a line and ends it
27		# with a { identifies a versioned section.  The section name is
28		# the rest of the line with the + and { symbols removed.
29		# Triggering this rule sets in_sec to 1, which actives the
30		# symbol rule below
31		/^.*{/ {
32			gsub("+", "");
33			if (in_map == 1) {
34				sec=$(NF-1); in_sec=1;
35			}
36		}
37
38		# This rule identifies the end of a section, and disables the
39		# symbol rule
40		/.*}/ {in_sec=0}
41
42		# This rule matches on a + followed by any characters except a :
43		# (which denotes a global vs local segment), and ends with a ;.
44		# The semicolon is removed and the symbol is printed with its
45		# association file name and version section, along with an
46		# indicator that the symbol is a new addition.  Note this rule
47		# only works if we have found a version section in the rule
48		# above (hence the in_sec check) And found a map file (the
49		# in_map check).  If we are not in a map chunk, do nothing.  If
50		# we are in a map chunk but not a section chunk, record it as
51		# unknown.
52		/^+[^}].*[^:*];/ {gsub(";","");sym=$2;
53			if (in_map == 1) {
54				if (in_sec == 1) {
55					print map " " sym " " sec " add"
56				} else {
57					print map " " sym " unknown add"
58				}
59			}
60		}
61
62		# This is the same rule as above, but the rule matches on a
63		# leading - rather than a +, denoting that the symbol is being
64		# removed.
65		/^-[^}].*[^:*];/ {gsub(";","");sym=$2;
66			if (in_map == 1) {
67				if (in_sec == 1) {
68					print map " " sym " " sec " del"
69				} else {
70					print map " " sym " unknown del"
71				}
72			}
73		}' > "$mapdb"
74
75		sort -u "$mapdb" > "$mapdb.2"
76		mv -f "$mapdb.2" "$mapdb"
77
78}
79
80is_stable_section() {
81	[ "$1" != 'EXPERIMENTAL' ] && [ "$1" != 'INTERNAL' ]
82}
83
84check_for_rule_violations()
85{
86	local mapdb="$1"
87	local mname
88	local symname
89	local secname
90	local ar
91	local ret=0
92
93	while read mname symname secname ar
94	do
95		if [ "$ar" = "add" ]
96		then
97
98			if [ "$secname" = "unknown" ]
99			then
100				# Just inform the user of this occurrence, but
101				# don't flag it as an error
102				echo -n "INFO: symbol $symname is added but "
103				echo -n "patch has insufficient context "
104				echo -n "to determine the section name "
105				echo -n "please ensure the version is "
106				echo "EXPERIMENTAL"
107				continue
108			fi
109
110			oldsecname=$(sed -n \
111			"s#$mname $symname \(.*\) del#\1#p" "$mapdb")
112
113			# A symbol can not enter a stable section directly
114			if [ -z "$oldsecname" ]
115			then
116				if ! is_stable_section $secname
117				then
118					echo -n "INFO: symbol $symname has "
119					echo -n "been added to the "
120					echo -n "$secname section of the "
121					echo "version map"
122					continue
123				else
124					echo -n "ERROR: symbol $symname "
125					echo -n "is added in the $secname "
126					echo -n "section, but is expected to "
127					echo -n "be added in the EXPERIMENTAL "
128					echo "section of the version map"
129					ret=1
130					continue
131				fi
132			fi
133
134			# This symbol is moving inside a section, nothing to do
135			if [ "$oldsecname" = "$secname" ]
136			then
137				continue
138			fi
139
140			# This symbol is moving between two sections (the
141			# original section is a stable section).
142			# This can be legit, just warn.
143			if is_stable_section $oldsecname
144			then
145				echo -n "INFO: symbol $symname is being "
146				echo -n "moved from $oldsecname to $secname. "
147				echo -n "Ensure that it has gone through the "
148				echo "deprecation process"
149				continue
150			fi
151		else
152
153			if ! grep -q "$mname $symname .* add" "$mapdb" && \
154			   is_stable_section $secname
155			then
156				# Just inform users that stable
157				# symbols need to go through a deprecation
158				# process
159				echo -n "INFO: symbol $symname is being "
160				echo -n "removed, ensure that it has "
161				echo "gone through the deprecation process"
162			fi
163		fi
164	done < "$mapdb"
165
166	return $ret
167}
168
169trap clean_and_exit_on_sig EXIT
170
171mapfile=`mktemp -t dpdk.mapdb.XXXXXX`
172patch=$1
173exit_code=1
174
175clean_and_exit_on_sig()
176{
177	rm -f "$mapfile"
178	exit $exit_code
179}
180
181build_map_changes "$patch" "$mapfile"
182check_for_rule_violations "$mapfile"
183exit_code=$?
184rm -f "$mapfile"
185
186exit $exit_code
187