Skip to content

Add Symbol Versioning Support#3096

Open
skmcgrail wants to merge 12 commits into
aws:mainfrom
skmcgrail:washbear-symbol-ver
Open

Add Symbol Versioning Support#3096
skmcgrail wants to merge 12 commits into
aws:mainfrom
skmcgrail:washbear-symbol-ver

Conversation

@skmcgrail

@skmcgrail skmcgrail commented Mar 12, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds GNU ld symbol versioning (.map files) to libcrypto-awslc and libssl-awslc shared libraries, automatically enabled when building with -DENABLE_DIST_PKG=ON
  • Introduces symbol registry files (crypto/libcrypto.txt, ssl/libssl.txt) as the source of truth, with Go-based tooling (util/read_public_symbols/, util/generate_version_script/) to generate and maintain version scripts
  • Adds CI jobs for incremental and baseline symbol checks (in abidiff.yml) and multi-arch dist-pkg tests (Ubuntu 24.04, AL2, AL2023 × gcc/clang × x86_64/aarch64)
  • Expands dist-pkg CI from a single x86 job to a full matrix across architectures and OS images, splitting install vs runtime test phases

Details

Build system changes:

  • New cmake/GenerateVersionScript.cmake provides apply_version_script() to attach a .map file to a target
  • CMakeLists.txt probes for --undefined-version linker support (needed for lld compatibility) and sets ENABLE_SYMBOL_VERSIONING when SET_LIB_SONAME and BUILD_SHARED_LIBS are both true
  • crypto/CMakeLists.txt and ssl/CMakeLists.txt call apply_version_script() on their respective targets

Symbol management tooling:

  • util/read_public_symbols/main.go — parses headers to extract public API symbols and classify visibility (PUBLIC, PRIVATE, PRIVATE_CXX)
  • util/generate_version_script/main.go — generates .map files from registry .txt files
  • util/generate_initial_version_scripts.sh — bootstraps registries and maps from scratch
  • util/update_symbol_version.sh — adds new symbols to a new version node with inheritance

CI:

  • 4 new jobs in abidiff.yml: incremental and baseline symbol checks for both libraries
  • Dist-pkg tests moved from linux_x86_omnibus.yml (single job) to linux-multi-arch-omnibus.yml (full matrix with install/run split)
  • New Docker image (.github/docker_images/symbol_check/) and check script (check_symbols.sh)

Testing:

  • tests/ci/run_symbol_version_test.sh — comprehensive validation that versioned symbols are applied, no unversioned symbols leak, libraries link correctly, and version definitions are present
  • tests/ci/run_dist_pkg_run_tests.sh — runtime tests for installed dist-pkg libraries

Documentation:

  • docs/SymbolVersioning.md — full developer guide covering version evolution, CI policy, and troubleshooting
  • BUILDING.md and README.md updated with distribution packaging section

Test plan

  • Build with -DENABLE_DIST_PKG=ON -DBUILD_SHARED_LIBS=ON and verify readelf --version-info shows AWS_LC_1.0 on both .so files
  • Run tests/ci/run_symbol_version_test.sh locally
  • Verify CI passes: abidiff symbol check jobs (incremental + baseline) and multi-arch dist-pkg matrix
  • Confirm no unversioned dynamic symbols via nm -D libcrypto-awslc.so | grep ' T ' | grep -v '@'

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license.

@codecov-commenter

codecov-commenter commented Mar 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.12%. Comparing base (de73c3a) to head (0626c4d).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3096      +/-   ##
==========================================
- Coverage   78.14%   78.12%   -0.03%     
==========================================
  Files         689      689              
  Lines      123526   123563      +37     
  Branches    17196    17184      -12     
==========================================
+ Hits        96531    96535       +4     
- Misses      26078    26111      +33     
  Partials      917      917              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@skmcgrail skmcgrail marked this pull request as ready for review March 16, 2026 18:38
@skmcgrail skmcgrail requested a review from a team as a code owner March 16, 2026 18:38
Comment thread tests/ci/run_symbol_version_test.sh
Comment thread tests/ci/run_symbol_version_test.sh Outdated
Comment thread tests/ci/run_symbol_version_test.sh
@ozbenh

ozbenh commented May 25, 2026

Copy link
Copy Markdown

[IGNORE] Use different symbol versions for libcrypto and libssl. ie AWS_LC_SSL_1_0 and AWS_LC_CRYPTO_1_0. Otherwise the RPM provides/requires will get confused esp if one changes and not the other

[UPDATE] I am wrong here. It works fine to use the same version symbol, rpm namespaces it by soname anyways and that's how glibc etc... do it (all the sub libs have the same version symbol).

Comment thread docs/SymbolVersioning.md

```bash
# Generate new baseline
./util/extract_symbols.sh build/crypto/libcrypto-awslc.so.0 \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see an extract_symbols.sh in this PR. Does it need to be added?

Comment thread CMakeLists.txt
# Version scripts are derived from the symbol registry files and have stable
# filenames (crypto/libcrypto.map, ssl/libssl.map). The version node names are
# recorded in the registry (crypto/libcrypto.txt, ssl/libssl.txt).
if(SET_LIB_SONAME AND BUILD_SHARED_LIBS AND UNIX AND NOT APPLE)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SET_LIB_SONAME is also set in the default elseif(NOT ENABLE_PRE_SONAME_BUILD AND BUILD_SHARED_LIBS AND UNIX AND NOT APPLE) branch (L105), so this enables symbol versioning for every standard Linux shared build, and not just ENABLE_DIST_PKG?

That's broader than the PR description/docs state. If dist-pkg-only is intended:

if(ENABLE_DIST_PKG AND BUILD_SHARED_LIBS AND UNIX AND NOT APPLE)

Otherwise, we should document that versioning now applies to all SONAME shared builds.

Comment thread crypto/libcrypto.map
Comment on lines +1 to +5
# GNU ld version script for AWS-LC
# Auto-generated from symbol registry. Do not edit manually.
# To add new symbols: util/update_symbol_version.sh <new_version>
# To regenerate: util/generate_initial_version_scripts.sh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# Auto-generated from symbol registry. Do not edit manually.

Should we add a CI step that runs generate_version_script on both registries and git diff --exit-codes the maps to avoid drift?

awk '$2 == "T" && $3 !~ /@/ && $3 !~ /^_/ { print $3 }' | \
wc -l)

if [[ ${SSL_UNVERSIONED} -eq 0 ]]; then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This validates that exported symbols are versioned, but not that all symbols exported before this change are still exported. (Since local: *; will hide any OPENSSL_EXPORT symbol the generator missed, a gap in the registry is a silent symbol drop.)

Are we relying on the abidiff job to catch this problem? Is it running against the versioned .so?

# 2. All exported symbols have proper version tags
# 3. No unversioned symbols leak
# 4. Version definitions are present in shared libraries
# 5. Libraries can be linked and used correctly

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The registry is generated from a non-FIPS build (no FIPS define in the target sets), but this applies it to a FIPS build? (FIPS-gated OPENSSL_EXPORT symbols won't be registered and will be localized.)

Can we confirm this job actually exercises those exports rather than just linking?

REGISTRY_PATH="${CHECK_LIB}/lib${CHECK_LIB}.txt"

if [[ "${CHECK_LIB}" == "crypto" ]]; then
READ_FLAGS=(-exclude ssl.h -internal-dirs crypto)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generation scripts use -internal-dirs crypto,third_party/jitterentropy, so the JENT_* symbols are registered but never scanned here and will permanently surface under the "registered but not in headers" warning. Aligning the flags avoids the standing noise:

Suggested change
READ_FLAGS=(-exclude ssl.h -internal-dirs crypto)
READ_FLAGS=(-exclude ssl.h -internal-dirs crypto,third_party/jitterentropy)

-source-root . \
-emit-visibility \
"${READ_FLAGS[@]}" \
-out /tmp/header_syms.txt 2>/dev/null

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suppressing stderr here means a broken extraction produces an empty header_syms.txt, which makes the baseline check pass trivially (no unregistered symbols, everything just "missing").

Suggest dropping 2>/dev/null (or teeing to a log) so extraction failures are visible.

Comment thread docs/SymbolVersioning.md
Comment on lines +69 to +71
This produces:
- `build/crypto/libcrypto-awslc.so.0.0.0` - with AWS_LC_1.0 versioned symbols
- `build/ssl/libssl-awslc.so.0.0.0` - with AWS_LC_1.0 versioned symbols

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Several stale references:

  • The build output is now .so.1.x.x (ABI_VERSION bumped to 1).
  • The version scripts are crypto/libcrypto.map / ssl/libssl.map (L93-94).
  • util/extract_symbols.sh doesn't exist (L145, L242, L257-260 -- the tooling is read_public_symbols / generate_version_script / update_symbol_version.sh).
  • tests/ci/baselines/symbols/*.txt has moved to crypto/+ssl/.

# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0 OR ISC

set -exo pipefail

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:

Suggested change
set -exo pipefail
set -exuo pipefail

name: libcrypto symbol check (incremental)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: these new jobs use actions/checkout@v3 while the rest of the repo is now on v5/v6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants