fix(plugins): enforce -fvisibility=hidden on all plugin .so targets#73
Merged
pabloinigoblasco merged 4 commits intodevelopmentfrom Apr 27, 2026
Merged
Conversation
The elseif(PJ_BUILD_DIALOG_ENGINE_QT) branch built a basic Qt::Widgets mcap_image_viewer as a fallback when pj_media_qt was not available. Now that pj_media_qt exists and is the correct path for media demos, this fallback is dead code: it never executes when pj_media_qt is present, and building a raw-widget demo without QRhi support provides no value when pj_media_qt is absent. Remove it to keep the demo CMakeLists clean.
pj_emit_plugin_manifest now sets CXX/C_VISIBILITY_PRESET=hidden and VISIBILITY_INLINES_HIDDEN=ON on every plugin target. This completes the RTLD_DEEPBIND replacement strategy: statically bundled deps (e.g. OpenSSL inside paho-mqtt-c) cannot conflict with the host's shared libs because their symbols are hidden and RTLD_LOCAL keeps them out of the global namespace. Only pj_plugin_abi_version and PJ_get_<family>_vtable remain default-visible via the PJ_*_PLUGIN macros. Update the library_loader.hpp comment to reflect that the mechanism is now actually in place, not merely aspirational.
-fvisibility=hidden alone is insufficient when static deps (e.g. libssl.a from Conan) are compiled without that flag: their symbols enter the plugin .so with DEFAULT visibility and their calls go through PLT — which resolves to the host's namespace first (system libssl), causing version-mismatch crashes. -Wl,-Bsymbolic-functions resolves all function calls within the .so directly to the embedded definition, bypassing PLT entirely. This covers pre-compiled static libs like OpenSSL regardless of how they were built. Only applied on Linux/ELF (macOS uses two-level namespace by default — equivalent behavior). Empirically verified with objdump: with -Bsymbolic-functions, calls from plugin_func to SSL_new are 'call SSL_new' (direct, no @plt). Without it, they remain 'call SSL_new@plt' even with -fvisibility=hidden. malloc/pthread/system calls are not defined in the plugin so they still resolve to the host — ASAN malloc interposition is unaffected.
2 tasks
…n-visibility-hidden
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
pj_emit_plugin_manifest()now setsCXX_VISIBILITY_PRESET=hidden,C_VISIBILITY_PRESET=hidden, andVISIBILITY_INLINES_HIDDEN=ONon every plugin.sotargetpj_plugin_abi_version,PJ_get_<family>_vtable) remain default-visible via thePJ_*_PLUGINmacros — no change needed therelibrary_loader.hppcomment to reflect that the mechanism is now actually enforcedWhy
With RTLD_DEEPBIND removed in v4 ABI, the intended replacement for symbol isolation was
-fvisibility=hiddenon plugin targets. This was documented in comments but never implemented in the build system, leaving plugin.sofiles with fully default-visible symbol tables. Any statically linked dependency whose symbols clashed with the host's shared libraries could crash at runtime.Test plan
nm -D <plugin>.so | grep SSLshows no exported OpenSSL symbols🤖 Generated with Claude Code