summaryrefslogtreecommitdiffstats
path: root/src/liblzma/validate_map.sh
blob: dd1589d236e79776e0aab4b239b29fe88e7a187d (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
#!/bin/sh
# SPDX-License-Identifier: 0BSD

###############################################################################
#
# Check liblzma_*.map for certain types of errors.
#
# liblzma_generic.map is for FreeBSD and Solaris and possibly others
# except GNU/Linux.
#
# liblzma_linux.map is for GNU/Linux only. This and the matching extra code
# in the .c files make liblzma >= 5.2.7 compatible with binaries that were
# linked against ill-patched liblzma in RHEL/CentOS 7. By providing the
# compatibility in official XZ Utils release will hopefully prevent people
# from further copying the broken patch to other places when they want
# compatibility with binaries linked on RHEL/CentOS 7. The long version
# of the story:
#
#     RHEL/CentOS 7 shipped with 5.1.2alpha, including the threaded
#     encoder that is behind #ifdef LZMA_UNSTABLE in the API headers.
#     In 5.1.2alpha these symbols are under XZ_5.1.2alpha in liblzma.map.
#     API/ABI compatibility tracking isn't done between development
#     releases so newer releases didn't have XZ_5.1.2alpha anymore.
#
#     Later RHEL/CentOS 7 updated xz to 5.2.2 but they wanted to keep
#     the exported symbols compatible with 5.1.2alpha. After checking
#     the ABI changes it turned out that >= 5.2.0 ABI is backward
#     compatible with the threaded encoder functions from 5.1.2alpha
#     (but not vice versa as fixes and extensions to these functions
#     were made between 5.1.2alpha and 5.2.0).
#
#     In RHEL/CentOS 7, XZ Utils 5.2.2 was patched with
#     xz-5.2.2-compat-libs.patch to modify liblzma.map:
#
#       - XZ_5.1.2alpha was added with lzma_stream_encoder_mt and
#         lzma_stream_encoder_mt_memusage. This matched XZ Utils 5.1.2alpha.
#
#       - XZ_5.2 was replaced with XZ_5.2.2. It is clear that this was
#         an error; the intention was to keep using XZ_5.2 (XZ_5.2.2
#         has never been used in XZ Utils). So XZ_5.2.2 lists all
#         symbols that were listed under XZ_5.2 before the patch.
#         lzma_stream_encoder_mt and _mt_memusage are included too so
#         they are listed both here and under XZ_5.1.2alpha.
#
#     The patch didn't add any __asm__(".symver ...") lines to the .c
#     files. Thus the resulting liblzma.so exports the threaded encoder
#     functions under XZ_5.1.2alpha only. Listing the two functions
#     also under XZ_5.2.2 in liblzma.map has no effect without
#     matching .symver lines.
#
#     The lack of XZ_5.2 in RHEL/CentOS 7 means that binaries linked
#     against unpatched XZ Utils 5.2.x won't run on RHEL/CentOS 7.
#     This is unfortunate but this alone isn't too bad as the problem
#     is contained within RHEL/CentOS 7 and doesn't affect users
#     of other distributions. It could also be fixed internally in
#     RHEL/CentOS 7.
#
#     The second problem is more serious: In XZ Utils 5.2.2 the API
#     headers don't have #ifdef LZMA_UNSTABLE for obvious reasons.
#     This is true in RHEL/CentOS 7 version too. Thus now programs
#     using new APIs can be compiled without an extra #define. However,
#     the programs end up depending on symbol version XZ_5.1.2alpha
#     (and possibly also XZ_5.2.2) instead of XZ_5.2 as they would
#     with an unpatched XZ Utils 5.2.2. This means that such binaries
#     won't run on other distributions shipping XZ Utils >= 5.2.0 as
#     they don't provide XZ_5.1.2alpha or XZ_5.2.2; they only provide
#     XZ_5.2 (and XZ_5.0). (This includes RHEL/CentOS 8 as the patch
#     luckily isn't included there anymore with XZ Utils 5.2.4.)
#
#     Binaries built by RHEL/CentOS 7 users get distributed and then
#     people wonder why they don't run on some other distribution.
#     Seems that people have found out about the patch and been copying
#     it to some build scripts, seemingly curing the symptoms but
#     actually spreading the illness further and outside RHEL/CentOS 7.
#     Adding compatibility in an official XZ Utils release should work
#     as a vaccine against this ill patch and stop it from spreading.
#     The vaccine is kept GNU/Linux-only as other OSes should be immune
#     (hopefully it hasn't spread via some build script to other OSes).
#
# Author: Lasse Collin
#
###############################################################################

LC_ALL=C
export LC_ALL

STATUS=0

cd "$(dirname "$0")"

# Get the list of symbols that aren't defined in liblzma_generic.map.
SYMS=$(sed -n 's/^extern LZMA_API([^)]*) \([a-z0-9_]*\)(.*$/\1;/p' \
		api/lzma/*.h \
	| sort \
	| grep -Fve "$(sed '/[{}:*]/d;/^$/d;s/^	//' liblzma_generic.map)")

# Check that there are no old alpha or beta versions listed.
VER=$(cd ../.. && sh build-aux/version.sh)
NAMES=
case $VER in
	*alpha | *beta)
		NAMES=$(sed -n 's/^.*XZ_\([^ ]*\)\(alpha\|beta\) .*$/\1\2/p' \
			liblzma_generic.map | grep -Fv "$VER")
		;;
esac

# Check for duplicate lines. It can catch missing dependencies.
DUPS=$(sort liblzma_generic.map | sed '/^$/d;/^global:$/d' | uniq -d)

# Check that liblzma_linux.map is in sync with liblzma_generic.map.
# The RHEL/CentOS 7 compatibility symbols are in a fixed location
# so it makes it easy to remove them for comparison with liblzma_generic.map.
#
# NOTE: Putting XZ_5.2 before the compatibility symbols XZ_5.1.2alpha
# and XZ_5.2.2 in liblzma_linux.map is important: If liblzma_linux.map is
# incorrectly used without #define HAVE_SYMBOL_VERSIONS_LINUX, only the first
# occurrence of each function name will be used from liblzma_linux.map;
# the rest are ignored by the linker. Thus having XZ_5.2 before the
# compatibility symbols means that @@XZ_5.2 will be used for the symbols
# listed under XZ_5.2 {...} and the same function names later in
# the file under XZ_5.1.2alpha {...} and XZ_5.2.2 {...} will be
# ignored (@XZ_5.1.2alpha or @XZ_5.2.2 won't be added at all when
# the #define HAVE_SYMBOL_VERSIONS_LINUX isn't used).
IN_SYNC=
if ! sed '111,125d' liblzma_linux.map \
		| cmp -s - liblzma_generic.map; then
	IN_SYNC=no
fi

# Print error messages if needed.
if test -n "$SYMS$NAMES$DUPS$IN_SYNC"; then
	echo
	echo 'validate_map.sh found problems from liblzma_*.map:'
	echo

	if test -n "$SYMS"; then
		echo 'liblzma_generic.map lacks the following symbols:'
		echo "$SYMS"
		echo
	fi

	if test -n "$NAMES"; then
		echo 'Obsolete alpha or beta version names:'
		echo "$NAMES"
		echo
	fi

	if test -n "$DUPS"; then
		echo 'Duplicate lines:'
		echo "$DUPS"
		echo
	fi

	if test -n "$IN_SYNC"; then
		echo "liblzma_generic.map and liblzma_linux.map aren't in sync"
		echo
	fi

	STATUS=1
fi

# Exit status is 1 if problems were found, 0 otherwise.
exit "$STATUS"