summaryrefslogtreecommitdiff
path: root/devtools/check-symbol-change.sh
blob: 8da765081988e3dd7d32ede035fd0c25c181b347 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#!/bin/sh
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2018 Neil Horman <nhorman@tuxdriver.com>

build_map_changes()
{
	local fname="$1"
	local mapdb="$2"

	cat "$fname" | awk '
		# Initialize our variables
		BEGIN {map="";sym="";ar="";sec=""; in_sec=0; in_map=0}

		# Anything that starts with + or -, followed by an a
		# and ends in the string .map is the name of our map file
		# This may appear multiple times in a patch if multiple
		# map files are altered, and all section/symbol names
		# appearing between a triggering of this rule and the
		# next trigger of this rule are associated with this file
		/[-+] a\/.*\.map/ {map=$2; in_map=1}

		# Same pattern as above, only it matches on anything that
		# does not end in 'map', indicating we have left the map chunk.
		# When we hit this, turn off the in_map variable, which
		# supresses the subordonate rules below
		/[-+] a\/.*\.[^map]/ {in_map=0}

		# Triggering this rule, which starts a line and ends it
		# with a { identifies a versioned section.  The section name is
		# the rest of the line with the + and { symbols remvoed.
		# Triggering this rule sets in_sec to 1, which actives the
		# symbol rule below
		/^.*{/ {
			gsub("+", "");
			if (in_map == 1) {
				sec=$(NF-1); in_sec=1;
			}
		}

		# This rule idenfies the end of a section, and disables the
		# symbol rule
		/.*}/ {in_sec=0}

		# This rule matches on a + followed by any characters except a :
		# (which denotes a global vs local segment), and ends with a ;.
		# The semicolon is removed and the symbol is printed with its
		# association file name and version section, along with an
		# indicator that the symbol is a new addition.  Note this rule
		# only works if we have found a version section in the rule
		# above (hence the in_sec check) And found a map file (the
		# in_map check).  If we are not in a map chunk, do nothing.  If
		# we are in a map chunk but not a section chunk, record it as
		# unknown.
		/^+[^}].*[^:*];/ {gsub(";","");sym=$2;
			if (in_map == 1) {
				if (in_sec == 1) {
					print map " " sym " " sec " add"
				} else {
					print map " " sym " unknown add"
				}
			}
		}

		# This is the same rule as above, but the rule matches on a
		# leading - rather than a +, denoting that the symbol is being
		# removed.
		/^-[^}].*[^:*];/ {gsub(";","");sym=$2;
			if (in_map == 1) {
				if (in_sec == 1) {
					print map " " sym " " sec " del"
				} else {
					print map " " sym " unknown del"
				}
			}
		}' > "$mapdb"

		sort -u "$mapdb" > "$mapdb.2"
		mv -f "$mapdb.2" "$mapdb"

}

check_for_rule_violations()
{
	local mapdb="$1"
	local mname
	local symname
	local secname
	local ar
	local ret=0

	while read mname symname secname ar
	do
		if [ "$ar" = "add" ]
		then

			if [ "$secname" = "unknown" ]
			then
				# Just inform the user of this occurrence, but
				# don't flag it as an error
				echo -n "INFO: symbol $syname is added but "
				echo -n "patch has insuficient context "
				echo -n "to determine the section name "
				echo -n "please ensure the version is "
				echo "EXPERIMENTAL"
				continue
			fi

			oldsecname=$(sed -n \
			"s#$mname $symname \(.*\) del#\1#p" "$mapdb")

			# A symbol can not enter a non experimental
			# section directly
			if [ $? -ne 0 ] && [ "$secname" != 'EXPERIMENTAL' ]
			then
				echo -n "ERROR: symbol $symname "
				echo -n "is added in the $secname "
				echo -n "section, but is expected to "
				echo -n "be added in the EXPERIMENTAL "
				echo "section of the version map"
				ret=1
				continue
			fi

			# This symbol is moving inside a section, nothing to do
			if [ "$oldsecname" = "$secname" ]
			then
				continue
			fi

			# This symbol is moving between two sections (the
			# original section is not experimental).
			# This can be legit, just warn.
			if [ "$oldsecname" != 'EXPERIMENTAL' ]
			then
				echo -n "INFO: symbol $symname is being "
				echo -n "moved from $oldsecname to $secname. "
				echo -n "Ensure that it has gone through the "
				echo "deprecation process"
				continue
			fi
		else

			if ! grep -q "$mname $symname .* add" "$mapdb" && \
			   [ "$secname" != "EXPERIMENTAL" ]
			then
				# Just inform users that non-experimenal
				# symbols need to go through a deprecation
				# process
				echo -n "INFO: symbol $symname is being "
				echo -n "removed, ensure that it has "
				echo "gone through the deprecation process"
			fi
		fi
	done < "$mapdb"

	return $ret
}

trap clean_and_exit_on_sig EXIT

mapfile=`mktemp -t dpdk.mapdb.XXXXXX`
patch=$1
exit_code=1

clean_and_exit_on_sig()
{
	rm -f "$mapfile"
	exit $exit_code
}

build_map_changes "$patch" "$mapfile"
check_for_rule_violations "$mapfile"
exit_code=$?
rm -f "$mapfile"

exit $exit_code