Skip to content

Commit ce6e960

Browse files
authored
Add tests using nm to check so contents (#693)
We want to ensure that the symbols included in shared object files (.so, .dylib, .dll) are as expected. This verifies that our Autoconf and CMake builds are using the `-fvisibility` flags and attributes correctly. As it turns out, the CMake build on Solaris is not working, and was exposing internal symbols due to a CMake issue.
1 parent abc2ae6 commit ce6e960

File tree

10 files changed

+390
-5
lines changed

10 files changed

+390
-5
lines changed

.github/workflows/build.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ jobs:
5454
run: |
5555
make install "DESTDIR=`pwd`/install-dir"
5656
maint/RunManifestTest install-dir maint/manifest-makeinstall-linux
57+
maint/RunSymbolTest install-dir/usr/local/lib/ maint/
5758
5859
alpine:
5960
name: alpine
@@ -93,6 +94,7 @@ jobs:
9394
run: |
9495
make install "DESTDIR=`pwd`/install-dir"
9596
maint/RunManifestTest install-dir maint/manifest-makeinstall-linux
97+
maint/RunSymbolTest install-dir/usr/local/lib/ maint/
9698
9799
macos:
98100
name: macOS universal
@@ -117,6 +119,7 @@ jobs:
117119
cd build
118120
cmake --install . --prefix install-dir
119121
../maint/RunManifestTest install-dir ../maint/manifest-cmakeinstall-macos
122+
../maint/RunSymbolTest install-dir/lib/ ../maint/
120123
121124
windows:
122125
name: Windows
@@ -145,6 +148,7 @@ jobs:
145148
cd build
146149
cmake --install . --config Release --prefix install-dir
147150
../maint/RunManifestTest.ps1 install-dir ../maint/manifest-cmakeinstall-windows
151+
../maint/RunSymbolTest.ps1 install-dir/bin ../maint/
148152
149153
freebsd:
150154
name: FreeBSD
@@ -182,6 +186,7 @@ jobs:
182186
183187
make install "DESTDIR=`pwd`/install-dir"
184188
maint/RunManifestTest install-dir maint/manifest-makeinstall-freebsd
189+
maint/RunSymbolTest install-dir/usr/local/lib/ maint/
185190
186191
echo "== CMake =="
187192
cd ../build-cmake
@@ -192,6 +197,7 @@ jobs:
192197
ctest -j3 --output-on-failure
193198
cmake --install . --prefix install-dir
194199
../maint/RunManifestTest install-dir ../maint/manifest-cmakeinstall-freebsd
200+
../maint/RunSymbolTest install-dir/lib/ ../maint/
195201
196202
solaris:
197203
name: Solaris
@@ -251,6 +257,7 @@ jobs:
251257
252258
make install "DESTDIR=`pwd`/install-dir"
253259
maint/RunManifestTest install-dir maint/manifest-makeinstall-solaris
260+
maint/RunSymbolTest install-dir/usr/local/lib/ maint/
254261
255262
echo "== Autoconf, 64-bit =="
256263
cd ../build-autoconf-64
@@ -261,6 +268,7 @@ jobs:
261268
262269
make install "DESTDIR=`pwd`/install-dir"
263270
maint/RunManifestTest install-dir maint/manifest-makeinstall-solaris
271+
maint/RunSymbolTest install-dir/usr/local/lib/ maint/
264272
265273
echo "== CMake, 64-bit =="
266274
cd ../build-cmake-64
@@ -271,6 +279,7 @@ jobs:
271279
ctest -j3 --output-on-failure
272280
cmake --install . --prefix install-dir
273281
../maint/RunManifestTest install-dir ../maint/manifest-cmakeinstall-solaris
282+
../maint/RunSymbolTest install-dir/lib/ ../maint/
274283
275284
distcheck:
276285
name: Build & verify distribution

.github/workflows/dev.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ jobs:
112112
cd build
113113
cmake --install . --prefix install-dir
114114
../maint/RunManifestTest install-dir ../maint/manifest-cmakeinstall-linux
115+
../maint/RunSymbolTest install-dir/lib/ ../maint/
115116
116117
dodo:
117118
# Tests with: Autconf on oldest supported Ubuntu (in non-extended support)
@@ -139,6 +140,7 @@ jobs:
139140
run: |
140141
make install "DESTDIR=`pwd`/install-dir"
141142
maint/RunManifestTest install-dir maint/manifest-makeinstall-linux
143+
maint/RunSymbolTest install-dir/usr/local/lib/ maint/
142144
143145
wasp:
144146
# Tests with: French locale; oldest supported CMake; no JIT; -Os; libreadline
@@ -185,6 +187,7 @@ jobs:
185187
cd build
186188
cmake --install . --prefix install-dir
187189
../maint/RunManifestTest install-dir ../maint/manifest-cmakeinstall-linux
190+
../maint/RunSymbolTest install-dir/lib/ ../maint/
188191
189192
bat:
190193
# Tests with: MSVC 32-bit, and a variety of CMake options

CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,17 @@ set(CMAKE_C_STANDARD_REQUIRED TRUE)
119119

120120
set(CMAKE_C_VISIBILITY_PRESET hidden)
121121

122+
# Solaris-specific fix for "CMAKE_C_VISIBILITY_PRESET": this feature was only
123+
# recently added to CMake for the `cc` compiler (Oracle Developer Studio). The
124+
# CMake version from OpenCSW and Oracle's package repository is too old and
125+
# requires this fix.
126+
if (CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND
127+
CMAKE_VERSION VERSION_LESS 3.31 AND
128+
CMAKE_C_COMPILER_ID STREQUAL "SunPro" AND
129+
CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 5.15)
130+
set(CMAKE_C_COMPILE_OPTIONS_VISIBILITY "-fvisibility=")
131+
endif()
132+
122133
# The following policies have been set in the PCRE2 CMake file in the past.
123134
# Since we specify a minimum of CMake 3.15, these are no longer required.
124135
# cmake_policy(SET CMP0063 NEW)

maint/RunManifestTest

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
# Script to test a directory listing. We use this to verify that the list of
44
# files installed by "make install" or "cmake --install" matches what we expect.
55

6+
set -e
7+
68
LANG=C # Ensure stable ordering of `sort` output
79
export LANG
810

@@ -17,14 +19,10 @@ expected_manifest="$2"
1719
base=`basename $expected_manifest`
1820

1921
sed=sed
20-
grep=grep
21-
# Helpers for Solaris
22+
# Helper for Solaris
2223
if [ -f /usr/bin/gsed ] ; then
2324
sed=/usr/bin/gsed
2425
fi
25-
if [ -f /usr/bin/ggrep ] ; then
26-
grep=/usr/bin/ggrep
27-
fi
2826

2927
find "$input_dir" -print | \
3028
sort | \

maint/RunSymbolTest

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#! /bin/sh
2+
3+
# Script to test that all the symbols of a shared object are as expected.
4+
5+
set -e
6+
7+
LANG=C # Ensure stable ordering of `sort` output
8+
export LANG
9+
10+
if [ "$1" = "" -o "$2" = "" ] ; then
11+
echo "Usage: $0 <so_dir> <manifest_dir>" >&2
12+
exit 1
13+
fi
14+
15+
input_dir="$1"
16+
manifest_dir="$2"
17+
18+
sed=sed
19+
grep=grep
20+
# Helpers for Solaris
21+
if [ -f /usr/bin/gsed ] ; then
22+
sed=/usr/bin/gsed
23+
fi
24+
if [ -f /usr/bin/ggrep ] ; then
25+
grep=/usr/bin/ggrep
26+
fi
27+
28+
nm="nm -B -D"
29+
if [ "`uname -s`" = "SunOS" ]; then
30+
nm="nm -p -h -D -g"
31+
elif [ "`uname -s`" = "Darwin" ]; then
32+
nm="nm -B -g"
33+
fi
34+
35+
so_ext=so
36+
so_mangling() { cat; }
37+
if [ "`uname -s`" = "Darwin" ]; then
38+
so_ext=dylib
39+
so_mangling()
40+
{
41+
sed -E -e 's/_([_0-9a-zA-Z]+)$/\1/g'
42+
}
43+
fi
44+
45+
for so_name in "libpcre2-8" "libpcre2-16" "libpcre2-32" "libpcre2-posix"; do
46+
expected_file="$manifest_dir/manifest-$so_name.so"
47+
so_file="$input_dir/$so_name.$so_ext"
48+
base=`basename $expected_file`
49+
50+
$nm "$so_file" | \
51+
$sed -E -e 's/^[0-9a-fA-F]* *//g' | \
52+
$grep -E -v '^[Uw] ' | \
53+
$grep -E -v ' (_init|_fini)$' | \
54+
$grep -E -v ' (_end|_DYNAMIC|_GLOBAL_OFFSET_TABLE_|_PROCEDURE_LINKAGE_TABLE_|_edata|_etext)$' | \
55+
so_mangling | \
56+
sort \
57+
> "$base"
58+
59+
if ! diff -u "$expected_file" "$base"; then
60+
echo "Shared object contents for $so_file differ from expected" >&2
61+
62+
echo "===Actual===" >&2
63+
cat "$base" >&2
64+
echo "===End===" >&2
65+
66+
exit 1
67+
fi
68+
69+
echo "Shared object contents for $so_file match expected"
70+
rm -f "$base"
71+
72+
done

maint/RunSymbolTest.ps1

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Script to test that all the symbols of a DLL are as expected.
2+
3+
param (
4+
[Parameter(Mandatory=$true)]
5+
[string]$inputDir,
6+
7+
[Parameter(Mandatory=$true)]
8+
[string]$manifestDir
9+
)
10+
11+
if ((-not $inputDir) -or (-not $manifestDir)) {
12+
throw "Usage: .\RunSymbolTest.ps1 <dll_dir> <manifest_dir>"
13+
}
14+
15+
$dllNames = @("pcre2-8", "pcre2-16", "pcre2-32", "pcre2-posix")
16+
17+
foreach ($dllName in $dllNames) {
18+
$expectedFile = Join-Path $manifestDir ("manifest-lib$dllName.so")
19+
$dllFile = Join-Path $inputDir ("$dllName.dll")
20+
$base = [System.IO.Path]::GetFileName($expectedFile)
21+
22+
# Get path to dumpbin using vswhere
23+
$vswhere = "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"
24+
$dumpbin = & $vswhere -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -find VC\Tools\MSVC\*\bin\Hostx64\x64\dumpbin.exe | Select-Object -First 1
25+
26+
$actualSymbols = & $dumpbin /exports $dllFile |
27+
ForEach-Object {
28+
if ($_ -match '^\s*\d+\s+[0-9A-Fa-f]+\s+[0-9A-Fa-f]+\s+(\S+)') {
29+
"T $($matches[1])"
30+
}
31+
} |
32+
Where-Object {
33+
$_ -match '^T '
34+
} |
35+
Sort-Object
36+
37+
$actualOutput = ($actualSymbols -join "`n") + "`n"
38+
$null = New-Item -Force $base -Value $actualOutput
39+
40+
$expectedOutput = Get-Content -Path $expectedFile -Raw
41+
$actualOutput = Get-Content -Path $base -Raw
42+
43+
if ($expectedOutput -ne $actualOutput) {
44+
Write-Host "Shared object contents for $dllFile differ from expected"
45+
Write-Host "===Actual==="
46+
Write-Host $actualOutput
47+
Write-Host "===End==="
48+
throw "Symbol test failed"
49+
} else {
50+
Write-Host "Shared object contents for $dllFile match expected"
51+
}
52+
53+
Remove-Item -Path $base -Force
54+
}

maint/manifest-libpcre2-16.so

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
T pcre2_callout_enumerate_16
2+
T pcre2_code_copy_16
3+
T pcre2_code_copy_with_tables_16
4+
T pcre2_code_free_16
5+
T pcre2_compile_16
6+
T pcre2_compile_context_copy_16
7+
T pcre2_compile_context_create_16
8+
T pcre2_compile_context_free_16
9+
T pcre2_config_16
10+
T pcre2_convert_context_copy_16
11+
T pcre2_convert_context_create_16
12+
T pcre2_convert_context_free_16
13+
T pcre2_converted_pattern_free_16
14+
T pcre2_dfa_match_16
15+
T pcre2_general_context_copy_16
16+
T pcre2_general_context_create_16
17+
T pcre2_general_context_free_16
18+
T pcre2_get_error_message_16
19+
T pcre2_get_mark_16
20+
T pcre2_get_match_data_heapframes_size_16
21+
T pcre2_get_match_data_size_16
22+
T pcre2_get_ovector_count_16
23+
T pcre2_get_ovector_pointer_16
24+
T pcre2_get_startchar_16
25+
T pcre2_jit_compile_16
26+
T pcre2_jit_free_unused_memory_16
27+
T pcre2_jit_match_16
28+
T pcre2_jit_stack_assign_16
29+
T pcre2_jit_stack_create_16
30+
T pcre2_jit_stack_free_16
31+
T pcre2_maketables_16
32+
T pcre2_maketables_free_16
33+
T pcre2_match_16
34+
T pcre2_match_context_copy_16
35+
T pcre2_match_context_create_16
36+
T pcre2_match_context_free_16
37+
T pcre2_match_data_create_16
38+
T pcre2_match_data_create_from_pattern_16
39+
T pcre2_match_data_free_16
40+
T pcre2_pattern_convert_16
41+
T pcre2_pattern_info_16
42+
T pcre2_serialize_decode_16
43+
T pcre2_serialize_encode_16
44+
T pcre2_serialize_free_16
45+
T pcre2_serialize_get_number_of_codes_16
46+
T pcre2_set_bsr_16
47+
T pcre2_set_callout_16
48+
T pcre2_set_character_tables_16
49+
T pcre2_set_compile_extra_options_16
50+
T pcre2_set_compile_recursion_guard_16
51+
T pcre2_set_depth_limit_16
52+
T pcre2_set_glob_escape_16
53+
T pcre2_set_glob_separator_16
54+
T pcre2_set_heap_limit_16
55+
T pcre2_set_match_limit_16
56+
T pcre2_set_max_pattern_compiled_length_16
57+
T pcre2_set_max_pattern_length_16
58+
T pcre2_set_max_varlookbehind_16
59+
T pcre2_set_newline_16
60+
T pcre2_set_offset_limit_16
61+
T pcre2_set_optimize_16
62+
T pcre2_set_parens_nest_limit_16
63+
T pcre2_set_recursion_limit_16
64+
T pcre2_set_recursion_memory_management_16
65+
T pcre2_set_substitute_callout_16
66+
T pcre2_set_substitute_case_callout_16
67+
T pcre2_substitute_16
68+
T pcre2_substring_copy_byname_16
69+
T pcre2_substring_copy_bynumber_16
70+
T pcre2_substring_free_16
71+
T pcre2_substring_get_byname_16
72+
T pcre2_substring_get_bynumber_16
73+
T pcre2_substring_length_byname_16
74+
T pcre2_substring_length_bynumber_16
75+
T pcre2_substring_list_free_16
76+
T pcre2_substring_list_get_16
77+
T pcre2_substring_nametable_scan_16
78+
T pcre2_substring_number_from_name_16

0 commit comments

Comments
 (0)