termux_step_massage: enhance symbol checking (#18233)

So that we dont have to physically own old phones to check issues like
these after package creation but during package creation.

CANNOT LINK EXECUTABLE "executable": cannot locate symbol "symbol"

The checks are mandatory! This will add around 5mins for large packages
on CI. Parser can be added later to reduce number of symbols to check.

New variables are added:

TERMUX_PKG_EXTRA_UNDEF_SYMBOLS_TO_CHECK
to facilitate specific symbols checks on specific packages

TERMUX_PKG_UNDEF_SYMBOLS_FILES
list of files that are intended to have undefined symbols
This commit is contained in:
Jia Yuan Lo 2024-04-27 12:09:32 +08:00 committed by GitHub
parent 4e618dfc52
commit 56c04aafc4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 2274 additions and 12 deletions

View File

@ -176,20 +176,93 @@ termux_step_massage() {
# Check so that package is not affected by
# https://github.com/android/ndk/issues/1614, or
# https://github.com/termux/termux-packages/issues/9944
if [ "$TERMUX_PACKAGE_LIBRARY" = "bionic" ] && [ -d "lib" ]; then
SYMBOLS="$($READELF -s $($TERMUX_HOST_PLATFORM-clang -print-libgcc-file-name) | grep "FUNC GLOBAL HIDDEN" | awk '{print $8}')"
if [[ "${TERMUX_PACKAGE_LIBRARY}" == "bionic" ]]; then
echo "INFO: READELF=${READELF} ... $(command -v ${READELF})"
export pattern_file=$(mktemp)
echo "INFO: Generating symbols regex to ${pattern_file}"
local t0=$(get_epoch)
local SYMBOLS=$(${READELF} -s $(${TERMUX_HOST_PLATFORM}-clang -print-libgcc-file-name) | grep -E "FUNC[[:space:]]+GLOBAL[[:space:]]+HIDDEN" | awk '{ print $8 }')
SYMBOLS+=" $(echo libandroid_{sem_{open,close,unlink},shm{ctl,get,at,dt}})"
SYMBOLS+=" $(echo backtrace{,_symbols{,_fd}})"
SYMBOLS+=" posix_spawn posix_spawnp"
grep_pattern="$(create_grep_pattern $SYMBOLS)"
for lib in $(find lib -name "*.so"); do
if ! $READELF -h "$lib" &> /dev/null; then
continue
# TODO replace grep all symbols with a parser
SYMBOLS+=" $(grep "^ " ${TERMUX_SCRIPTDIR}/scripts/lib{c,dl,m}.map.txt | cut -d":" -f2 | grep ";" | grep -v '*' | sed -e "s/^ //" -e "s/;.*//")"
SYMBOLS+=" ${TERMUX_PKG_EXTRA_UNDEF_SYMBOLS_TO_CHECK}"
SYMBOLS=$(echo $SYMBOLS | tr " " "\n" | sort | uniq)
create_grep_pattern ${SYMBOLS} > "${pattern_file}"
local t1=$(get_epoch)
echo "INFO: Done ... $((t1-t0))s"
echo "INFO: Total symbols $(echo ${SYMBOLS} | wc -w)"
local nproc=$(nproc)
echo "INFO: Identifying files with nproc=${nproc}"
local t0=$(get_epoch)
local files=$(find . -type f)
# use bash to see if llvm-readelf crash
# https://github.com/llvm/llvm-project/issues/89534
local valid=$(echo "${files}" | xargs -P"${nproc}" -i bash -c 'if ${READELF} -h {} &>/dev/null; then echo {}; fi')
local t1=$(get_epoch)
echo "INFO: Done ... $((t1-t0))s"
local numberOfFiles=$(echo "${files}" | wc -l)
local numberOfValid=$(echo "${valid}" | wc -l)
echo "INFO: Found ${numberOfValid} / ${numberOfFiles} files"
if [[ "${numberOfValid}" -gt "${numberOfFiles}" ]]; then
termux_error_exit "${numberOfValid} > ${numberOfFiles}"
fi
echo "INFO: Running symbol checks on ${numberOfValid} files with nproc=${nproc}"
local t0=$(get_epoch)
local undef=$(echo "${valid}" | xargs -P"${nproc}" -i sh -c '${READELF} -s {} | grep -Ef "${pattern_file}"')
local t1=$(get_epoch)
echo "INFO: Done ... $((t1-t0))s"
[[ -n "${undef}" ]] && echo "INFO: Found files with undefined symbols"
if [[ "${TERMUX_PKG_UNDEF_SYMBOLS_FILES}" == "all" ]]; then
echo "INFO: Skipping output result as TERMUX_PKG_UNDEF_SYMBOLS_FILES=all"
undef=""
fi
if [[ -n "${undef}" ]]; then
echo "INFO: Showing result"
local t0=$(get_epoch)
local e=0
local c=0
local valid_s=$(echo "${valid}" | sort)
local f excluded_f
while IFS= read -r f; do
# exclude object, static files
case "${f}" in
*.a) (( e &= ~1 )) || : ;;
*.o) (( e &= ~1 )) || : ;;
*.rlib) (( e &= ~1 )) || : ;;
*) (( e |= 1 )) || : ;;
esac
while IFS= read -r excluded_f; do
[[ "${f}" == ${excluded_f} ]] && (( e &= ~1 )) && break
done < <(echo "${TERMUX_PKG_UNDEF_SYMBOLS_FILES}")
[[ "${TERMUX_PKG_UNDEF_SYMBOLS_FILES}" == "error" ]] && (( e |= 1 )) || :
[[ $(( e & 1 )) == 0 ]] && echo "SKIP: ${f}" && continue
local undef_s=$(${READELF} -s "${f}" | grep -Ef "${pattern_file}")
if [[ -n "${undef_s}" ]]; then
((c++)) || :
if [[ $(( e & 1 )) != 0 ]]; then
echo -e "ERROR: ${f} contains undefined symbols:\n${undef_s}" >&2
(( e |= 2 )) || :
else
local undef_su=$(echo "${undef_s}" | awk '{ print $8 }' | sort | uniq)
local undef_su_len=$(echo ${undef_su} | wc -w)
echo "SKIP: ${f} contains undefined symbols: ${undef_su_len}" >&2
fi
fi
done < <(echo "${valid_s}")
local t1=$(get_epoch)
echo "INFO: Done ... $((t1-t0))s"
echo "INFO: Found ${c} files with undefined symbols after exclusion"
if [[ "${c}" -gt "${numberOfValid}" ]]; then
termux_error_exit "${c} > ${numberOfValid}"
fi
if $READELF -s "$lib" | egrep "${grep_pattern}" &> /dev/null; then
termux_error_exit "$lib contains undefined symbols:\n$($READELF -s "$lib" | egrep "${grep_pattern}")"
fi
done
[[ $(( e & 2 )) != 0 ]] && termux_error_exit "Refer above"
fi
rm -f "${pattern_file}"
unset pattern_file
fi
if [ "$TERMUX_PACKAGE_FORMAT" = "debian" ]; then
@ -216,3 +289,9 @@ create_grep_pattern() {
echo -n "|$symbol_type$arg"'$'
done
}
get_epoch() {
[[ -e /proc/uptime ]] && cut -d"." -f1 /proc/uptime && return
[[ -n "$(command -v date)" ]] && date +%s && return
echo 0
}

View File

@ -146,6 +146,7 @@ termux_step_setup_variables() {
TERMUX_PKG_EXTRA_CONFIGURE_ARGS=""
TERMUX_PKG_EXTRA_HOSTBUILD_CONFIGURE_ARGS=""
TERMUX_PKG_EXTRA_MAKE_ARGS=""
TERMUX_PKG_EXTRA_UNDEF_SYMBOLS_TO_CHECK="" # space-separated undefined symbols to check in termux_step_massaging
TERMUX_PKG_FORCE_CMAKE=false # if the package has autotools as well as cmake, then set this to prefer cmake
TERMUX_PKG_GIT_BRANCH="" # branch defaults to 'v$TERMUX_PKG_VERSION' unless this variable is defined
TERMUX_PKG_GO_USE_OLDER=false # set to true to use the older supported release of Go.
@ -174,6 +175,7 @@ termux_step_setup_variables() {
TERMUX_PKG_SRCDIR=$TERMUX_TOPDIR/$TERMUX_PKG_NAME/src
TERMUX_PKG_SUGGESTS=""
TERMUX_PKG_TMPDIR=$TERMUX_TOPDIR/$TERMUX_PKG_NAME/tmp
TERMUX_PKG_UNDEF_SYMBOLS_FILES="" # maintainer acknowledges these files have undefined symbols will not result in broken packages, eg: all, *.elf, ./path/to/file. "error" to always print results as errors
TERMUX_PKG_SERVICE_SCRIPT=() # Fill with entries like: ("daemon name" 'script to execute'). Script is echoed with -e so can contain \n for multiple lines
TERMUX_PKG_GROUPS="" # https://wiki.archlinux.org/title/Pacman#Installing_package_groups
TERMUX_PKG_ON_DEVICE_BUILD_NOT_SUPPORTED=false # if the package does not support compilation on a device, then this package should not be compiled on devices

1823
scripts/libc.map.txt Normal file

File diff suppressed because it is too large Load Diff

49
scripts/libdl.map.txt Normal file
View File

@ -0,0 +1,49 @@
#
# Copyright (C) 2015 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LIBC {
global:
android_dlopen_ext; # introduced=21
dl_iterate_phdr; # introduced-arm=21
dl_unwind_find_exidx; # arm
dladdr;
dlclose;
dlerror;
dlopen;
dlsym;
local:
*;
};
LIBC_N {
global:
android_get_application_target_sdk_version; # introduced=24 versioned=29
dlvsym; # introduced=24
} LIBC;
LIBC_OMR1 { # introduced=27
global:
__cfi_shadow_size;
__cfi_slowpath;
__cfi_slowpath_diag;
} LIBC_N;
LIBC_PLATFORM {
global:
android_get_LD_LIBRARY_PATH;
__cfi_init;
android_handle_signal;
} LIBC_OMR1;

309
scripts/libm.map.txt Normal file
View File

@ -0,0 +1,309 @@
LIBC {
global:
__fe_dfl_env; # var
__signbit;
__signbitf;
__signbitl;
acos;
acosf;
acosh;
acoshf;
acoshl; # introduced=21
acosl; # introduced=21
asin;
asinf;
asinh;
asinhf;
asinhl; # introduced=21
asinl; # introduced=21
atan;
atan2;
atan2f;
atan2l; # introduced=21
atanf;
atanh;
atanhf;
atanhl; # introduced=21
atanl; # introduced=21
cabs; # introduced=23
cabsf; # introduced=23
cabsl; # introduced-arm=21 introduced-arm64=23 introduced-x86=21 introduced-x86_64=23
cacos; # introduced=23
cacosf; # introduced=23
cacosh; # introduced=23
cacoshf; # introduced=23
carg; # introduced=23
cargf; # introduced=23
cargl; # introduced=23
casin; # introduced=23
casinf; # introduced=23
casinh; # introduced=23
casinhf; # introduced=23
catan; # introduced=23
catanf; # introduced=23
catanh; # introduced=23
catanhf; # introduced=23
cbrt;
cbrtf;
cbrtl; # introduced=21
ccos; # introduced=23
ccosf; # introduced=23
ccosh; # introduced=23
ccoshf; # introduced=23
ceil;
ceilf;
ceill;
cexp; # introduced=23
cexpf; # introduced=23
cimag; # introduced=23
cimagf; # introduced=23
cimagl; # introduced=23
conj; # introduced=23
conjf; # introduced=23
conjl; # introduced=23
copysign;
copysignf;
copysignl;
cos;
cosf;
cosh;
coshf;
coshl; # introduced=21
cosl; # introduced=21
cproj; # introduced=23
cprojf; # introduced=23
cprojl; # introduced-arm=21 introduced-arm64=23 introduced-x86=21 introduced-x86_64=23
creal; # introduced=23
crealf; # introduced=23
creall; # introduced=23
csin; # introduced=23
csinf; # introduced=23
csinh; # introduced=23
csinhf; # introduced=23
csqrt; # introduced=23
csqrtf; # introduced=23
csqrtl; # introduced-arm=21 introduced-arm64=23 introduced-x86=21 introduced-x86_64=23
ctan; # introduced=23
ctanf; # introduced=23
ctanh; # introduced=23
ctanhf; # introduced=23
drem;
dremf;
erf;
erfc;
erfcf;
erfcl; # introduced=21
erff;
erfl; # introduced=21
exp;
exp2;
exp2f;
exp2l; # introduced=21
expf;
expl; # introduced=21
expm1;
expm1f;
expm1l; # introduced=21
fabs;
fabsf;
fabsl;
fdim;
fdimf;
fdiml;
feclearexcept; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
fedisableexcept; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
feenableexcept; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
fegetenv; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
fegetexcept; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
fegetexceptflag; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
fegetround; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
feholdexcept; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
feraiseexcept; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
fesetenv; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
fesetexceptflag; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
fesetround; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
fetestexcept; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
feupdateenv; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
finite;
finitef;
floor;
floorf;
floorl;
fma;
fmaf;
fmal; # introduced=21
fmax;
fmaxf;
fmaxl;
fmin;
fminf;
fminl;
fmod;
fmodf;
fmodl; # introduced=21
frexp;
frexpf;
frexpl; # introduced=21
gamma;
gamma_r;
gammaf;
gammaf_r;
hypot;
hypotf;
hypotl; # introduced=21
ilogb;
ilogbf;
ilogbl;
j0;
j0f;
j1;
j1f;
jn;
jnf;
ldexpf;
ldexpl;
lgamma;
lgamma_r;
lgammaf;
lgammaf_r;
lgammal; # introduced=21
lgammal_r; # introduced=23
llrint;
llrintf;
llrintl; # introduced=21
llround;
llroundf;
llroundl;
log;
log10;
log10f;
log10l; # introduced=21
log1p;
log1pf;
log1pl; # introduced=21
log2; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
log2f; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
log2l; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
logb;
logbf;
logbl; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
logf;
logl; # introduced=21
lrint;
lrintf;
lrintl; # introduced=21
lround;
lroundf;
lroundl;
modf;
modff;
modfl; # introduced=21
nan; # introduced-arm=13 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
nanf; # introduced-arm=13 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
nanl; # introduced-arm=13 introduced-arm64=21 introduced-x86=13 introduced-x86_64=21
nearbyint;
nearbyintf;
nearbyintl; # introduced=21
nextafter;
nextafterf;
nextafterl; # introduced=21
nexttoward; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
nexttowardf;
nexttowardl; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
pow;
powf;
powl; # introduced=21
remainder;
remainderf;
remainderl; # introduced=21
remquo;
remquof;
remquol; # introduced=21
rint;
rintf;
rintl; # introduced=21
round;
roundf;
roundl;
scalb;
scalbf;
scalbln; # introduced-arm=9 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
scalblnf; # introduced-arm=9 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
scalblnl; # introduced-arm=9 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
scalbn;
scalbnf;
scalbnl;
signgam; # var
significand;
significandf;
significandl; # introduced=21
sin;
sincos;
sincosf;
sincosl;
sinf;
sinh;
sinhf;
sinhl; # introduced=21
sinl; # introduced=21
sqrt;
sqrtf;
sqrtl; # introduced=21
tan;
tanf;
tanh;
tanhf;
tanhl; # introduced=21
tanl; # introduced=21
tgamma;
tgammaf; # introduced-arm=13 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
tgammal; # introduced=21
trunc;
truncf;
truncl;
y0;
y0f;
y1;
y1f;
yn;
ynf;
local:
*;
};
LIBC_O { # introduced=O
global:
cacoshl;
cacosl;
casinhl;
casinl;
catanhl;
catanl;
ccoshl;
ccosl;
cexpl;
clog;
clogf;
clogl;
cpow;
cpowf;
cpowl;
csinhl;
csinl;
ctanhl;
ctanl;
} LIBC;
LIBC_DEPRECATED { # arm platform-only
global: # arm
__aeabi_d2lz; # arm
__aeabi_d2ulz; # arm
__aeabi_f2lz; # arm
__aeabi_f2ulz; # arm
__aeabi_l2d; # arm
__fixdfdi; # arm
__fixsfdi; # arm
__fixunsdfdi; # arm
__fixunssfdi; # arm
__floatdidf; # arm
} LIBC_O; # arm