| #! /bin/sh | |
| # Script to test that all the symbols of a shared object are as expected. | |
| set -e | |
| # Ensure stable ordering of `sort` output | |
| LANG=C | |
| LC_ALL=C | |
| export LANG LC_ALL | |
| if [ "$#" -ne 2 ]; then | |
| echo "Usage: $0 <so_dir> <manifest_dir>" >&2 | |
| exit 1 | |
| fi | |
| input_dir="$1" | |
| manifest_dir="$2" | |
| sed=sed | |
| grep=grep | |
| # Helpers for Solaris | |
| if [ -f /usr/bin/gsed ] ; then | |
| sed=/usr/bin/gsed | |
| fi | |
| if [ -f /usr/bin/ggrep ] ; then | |
| grep=/usr/bin/ggrep | |
| fi | |
| nm="nm -B -D" | |
| if [ "`uname -s`" = "Linux" ]; then | |
| nm="$nm --with-symbol-versions" | |
| elif [ "`uname -s`" = "FreeBSD" ]; then | |
| # Use llvm-nm to get symbol version information | |
| nm="llvm-nm -B -D" | |
| elif [ "`uname -s`" = "SunOS" ]; then | |
| # Highly annoyingly, Solaris' nm doesn't show symbol versions, so here is a | |
| # laborious way to reformat the output of elfdump to be as we require. | |
| #nm="nm -p -h -D -g" | |
| nm=emulated_nm | |
| emulated_nm() | |
| { | |
| # Grab the versions from the version table, and convert into a sed script. | |
| VERSUB=`elfdump -v "$1" | \ | |
| $grep -E '^\s*\[[0-9]+\]' | \ | |
| $sed -E -e 's/\s+/,/g' | \ | |
| tr -d '\[\]' | \ | |
| cut -d',' -f 2,3 | \ | |
| $sed -E -e 's/([0-9]+),(.*)/s\/@@\1\/@@\2\/;/'` | |
| # Then grab the symbols and heavily reformat the output to match nm. | |
| elfdump -T SHT_DYNSYM "$1" | \ | |
| $grep -E '^\s*\[[0-9]+\]' | \ | |
| $sed -E -e 's/\s+/ /g' | \ | |
| cut -d' ' -f 3,8,9,10 | \ | |
| $sed -E -e 's/^0x//;s/([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*)/\1 \3 \4@@\2/;' | \ | |
| $sed -E -e 's/^([^ ]*) .text /\1 T /' | \ | |
| $sed -E -e 's/^([^ ]*) ([UA])(NDEF|BS) /\1 \2 /' | \ | |
| $sed -E -e "$VERSUB" | |
| } | |
| elif [ "`uname -s`" = "Darwin" ]; then | |
| nm="nm -B -g" | |
| fi | |
| supports_versions=1 | |
| if [ "`uname -s`" = "Darwin" ]; then | |
| supports_versions=0 | |
| fi | |
| so_ext=so | |
| so_mangling() { cat; } | |
| if [ "`uname -s`" = "Darwin" ]; then | |
| so_ext=dylib | |
| so_mangling() | |
| { | |
| $sed -E -e 's/_([_0-9a-zA-Z]+)$/\1/g' | |
| } | |
| fi | |
| for so_name in "libpcre2-8" "libpcre2-16" "libpcre2-32" "libpcre2-posix"; do | |
| expected_file="$manifest_dir/manifest-$so_name.so" | |
| so_file="$input_dir/$so_name.$so_ext" | |
| base=$(basename "$expected_file") | |
| $nm "$so_file" | \ | |
| $sed -E -e 's/^[0-9a-fA-F]* *//g' | \ | |
| $grep -E -v '^[Uw] ' | \ | |
| $grep -E -v '^A PCRE2_' | \ | |
| $grep -E -v ' (_init|_fini)($|@)' | \ | |
| $grep -E -v ' (__bss_start|_end|_DYNAMIC|_GLOBAL_OFFSET_TABLE_|_PROCEDURE_LINKAGE_TABLE_|_edata|_etext)($|@)' | \ | |
| so_mangling | \ | |
| sort \ | |
| > "$base.actual" | |
| if [ $supports_versions -eq 0 ]; then | |
| $sed -E -e 's/@.*$//' "$expected_file" \ | |
| > "$base.expected" | |
| else | |
| cp "$expected_file" "$base.expected" | |
| fi | |
| if ! diff -u "$base.expected" "$base.actual"; then | |
| echo "Shared object contents for $so_file differ from expected" | |
| echo "===Actual===" | |
| cat "$base.actual" | |
| echo "===End===" | |
| exit 1 | |
| fi | |
| echo "Shared object contents for $so_file match expected" | |
| rm -f "$base.expected" "$base.actual" | |
| done |