1#!/bin/sh 2 3############################################################################### 4# 5# Check liblzma_*.map for certain types of errors. 6# 7# liblzma_generic.map is for FreeBSD and Solaris and possibly others 8# except GNU/Linux. 9# 10# liblzma_linux.map is for GNU/Linux only. This and the matching extra code 11# in the .c files make liblzma >= 5.2.7 compatible with binaries that were 12# linked against ill-patched liblzma in RHEL/CentOS 7. By providing the 13# compatibility in official XZ Utils release will hopefully prevent people 14# from further copying the broken patch to other places when they want 15# compatibility with binaries linked on RHEL/CentOS 7. The long version 16# of the story: 17# 18# RHEL/CentOS 7 shipped with 5.1.2alpha, including the threaded 19# encoder that is behind #ifdef LZMA_UNSTABLE in the API headers. 20# In 5.1.2alpha these symbols are under XZ_5.1.2alpha in liblzma.map. 21# API/ABI compatibility tracking isn't done between development 22# releases so newer releases didn't have XZ_5.1.2alpha anymore. 23# 24# Later RHEL/CentOS 7 updated xz to 5.2.2 but they wanted to keep 25# the exported symbols compatible with 5.1.2alpha. After checking 26# the ABI changes it turned out that >= 5.2.0 ABI is backward 27# compatible with the threaded encoder functions from 5.1.2alpha 28# (but not vice versa as fixes and extensions to these functions 29# were made between 5.1.2alpha and 5.2.0). 30# 31# In RHEL/CentOS 7, XZ Utils 5.2.2 was patched with 32# xz-5.2.2-compat-libs.patch to modify liblzma.map: 33# 34# - XZ_5.1.2alpha was added with lzma_stream_encoder_mt and 35# lzma_stream_encoder_mt_memusage. This matched XZ Utils 5.1.2alpha. 36# 37# - XZ_5.2 was replaced with XZ_5.2.2. It is clear that this was 38# an error; the intention was to keep using XZ_5.2 (XZ_5.2.2 39# has never been used in XZ Utils). So XZ_5.2.2 lists all 40# symbols that were listed under XZ_5.2 before the patch. 41# lzma_stream_encoder_mt and _mt_memusage are included too so 42# they are listed both here and under XZ_5.1.2alpha. 43# 44# The patch didn't add any __asm__(".symver ...") lines to the .c 45# files. Thus the resulting liblzma.so exports the threaded encoder 46# functions under XZ_5.1.2alpha only. Listing the two functions 47# also under XZ_5.2.2 in liblzma.map has no effect without 48# matching .symver lines. 49# 50# The lack of XZ_5.2 in RHEL/CentOS 7 means that binaries linked 51# against unpatched XZ Utils 5.2.x won't run on RHEL/CentOS 7. 52# This is unfortunate but this alone isn't too bad as the problem 53# is contained within RHEL/CentOS 7 and doesn't affect users 54# of other distributions. It could also be fixed internally in 55# RHEL/CentOS 7. 56# 57# The second problem is more serious: In XZ Utils 5.2.2 the API 58# headers don't have #ifdef LZMA_UNSTABLE for obvious reasons. 59# This is true in RHEL/CentOS 7 version too. Thus now programs 60# using new APIs can be compiled without an extra #define. However, 61# the programs end up depending on symbol version XZ_5.1.2alpha 62# (and possibly also XZ_5.2.2) instead of XZ_5.2 as they would 63# with an unpatched XZ Utils 5.2.2. This means that such binaries 64# won't run on other distributions shipping XZ Utils >= 5.2.0 as 65# they don't provide XZ_5.1.2alpha or XZ_5.2.2; they only provide 66# XZ_5.2 (and XZ_5.0). (This includes RHEL/CentOS 8 as the patch 67# luckily isn't included there anymore with XZ Utils 5.2.4.) 68# 69# Binaries built by RHEL/CentOS 7 users get distributed and then 70# people wonder why they don't run on some other distribution. 71# Seems that people have found out about the patch and been copying 72# it to some build scripts, seemingly curing the symptoms but 73# actually spreading the illness further and outside RHEL/CentOS 7. 74# Adding compatibility in an official XZ Utils release should work 75# as a vaccine against this ill patch and stop it from spreading. 76# The vaccine is kept GNU/Linux-only as other OSes should be immune 77# (hopefully it hasn't spread via some build script to other OSes). 78# 79# Author: Lasse Collin 80# 81# This file has been put into the public domain. 82# You can do whatever you want with this file. 83# 84############################################################################### 85 86LC_ALL=C 87export LC_ALL 88 89STATUS=0 90 91cd "$(dirname "$0")" 92 93# Get the list of symbols that aren't defined in liblzma_generic.map. 94SYMS=$(sed -n 's/^extern LZMA_API([^)]*) \([a-z0-9_]*\)(.*$/\1;/p' \ 95 api/lzma/*.h \ 96 | sort \ 97 | grep -Fve "$(sed '/[{}:*]/d;/^$/d;s/^ //' liblzma_generic.map)") 98 99# Check that there are no old alpha or beta versions listed. 100VER=$(cd ../.. && sh build-aux/version.sh) 101NAMES= 102case $VER in 103 *alpha | *beta) 104 NAMES=$(sed -n 's/^.*XZ_\([^ ]*\)\(alpha\|beta\) .*$/\1\2/p' \ 105 liblzma_generic.map | grep -Fv "$VER") 106 ;; 107esac 108 109# Check for duplicate lines. It can catch missing dependencies. 110DUPS=$(sort liblzma_generic.map | sed '/^$/d;/^global:$/d' | uniq -d) 111 112# Check that liblzma_linux.map is in sync with liblzma_generic.map. 113# The RHEL/CentOS 7 compatibility symbols are in a fixed location 114# so it makes it easy to remove them for comparison with liblzma_generic.map. 115# 116# NOTE: Putting XZ_5.2 before the compatibility symbols XZ_5.1.2alpha 117# and XZ_5.2.2 in liblzma_linux.map is important: If liblzma_linux.map is 118# incorrectly used without #define HAVE_SYMBOL_VERSIONS_LINUX, only the first 119# occurrence of each function name will be used from liblzma_linux.map; 120# the rest are ignored by the linker. Thus having XZ_5.2 before the 121# compatibility symbols means that @@XZ_5.2 will be used for the symbols 122# listed under XZ_5.2 {...} and the same function names later in 123# the file under XZ_5.1.2alpha {...} and XZ_5.2.2 {...} will be 124# ignored (@XZ_5.1.2alpha or @XZ_5.2.2 won't be added at all when 125# the #define HAVE_SYMBOL_VERSIONS_LINUX isn't used). 126IN_SYNC= 127if ! sed '109,123d' liblzma_linux.map \ 128 | cmp -s - liblzma_generic.map; then 129 IN_SYNC=no 130fi 131 132# Print error messages if needed. 133if test -n "$SYMS$NAMES$DUPS$IN_SYNC"; then 134 echo 135 echo 'validate_map.sh found problems from liblzma_*.map:' 136 echo 137 138 if test -n "$SYMS"; then 139 echo 'liblzma_generic.map lacks the following symbols:' 140 echo "$SYMS" 141 echo 142 fi 143 144 if test -n "$NAMES"; then 145 echo 'Obsolete alpha or beta version names:' 146 echo "$NAMES" 147 echo 148 fi 149 150 if test -n "$DUPS"; then 151 echo 'Duplicate lines:' 152 echo "$DUPS" 153 echo 154 fi 155 156 if test -n "$IN_SYNC"; then 157 echo "liblzma_generic.map and liblzma_linux.map aren't in sync" 158 echo 159 fi 160 161 STATUS=1 162fi 163 164# Exit status is 1 if problems were found, 0 otherwise. 165exit "$STATUS" 166