diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index 6800c81d4..72716b945 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -146,6 +146,7 @@ if ! $(BOOST_ARCHIVE_LIST) {
# we suppress tests of our dlls when using static libraries
[ test-bsl-run test_dll_simple : : dll_a : static:no ]
+ [ test-bsl-run test_dll_base_pointer : : dll_polymorphic_base dll_polymorphic_derived2 : static:no ]
# [ test-bsl-run test_dll_plugin : : dll_derived2 : static:no linux:-ldl ]
[ test-bsl-run test_private_ctor ]
diff --git a/test/test_dll_base_pointer.cpp b/test/test_dll_base_pointer.cpp
new file mode 100644
index 000000000..8a938c65d
--- /dev/null
+++ b/test/test_dll_base_pointer.cpp
@@ -0,0 +1,75 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// test_dll_base_pointer.cpp
+
+// Copyright 2026 Gennaro Prota
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+
+// Regression test for issue #117. A derived class defined in a shared
+// library is serialized and deserialized through a pointer to its abstract
+// base, from an executable built with hidden symbol visibility.
+// Historically this failed on GCC/ELF: the per type serializer singletons
+// were duplicated across the shared library boundary, so the reader could not
+// map the class id back to the derived type. The round trip must recover an
+// object of the derived type.
+
+#include
+#include
+#include
+
+#include
+
+#include "test_tools.hpp"
+
+#ifndef BOOST_NO_CXX11_SMART_PTR
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+// polymorphic_derived2 (and its base, polymorphic_base) live in the shared
+// library this test links against
+#define POLYMORPHIC_DERIVED2_IMPORT
+#include "polymorphic_derived2.hpp"
+
+int test_main(int /* argc */, char * /* argv */ []){
+ const char * testfile = boost::archive::tmpnam(NULL);
+ BOOST_REQUIRE(NULL != testfile);
+
+ std::unique_ptr saved =
+ boost::make_unique();
+ {
+ std::ofstream os(testfile, std::ios::binary);
+ boost::archive::polymorphic_binary_oarchive oa(os);
+ boost::archive::polymorphic_oarchive & poa = oa;
+ poa << boost::serialization::make_nvp("ptr", saved);
+ }
+
+ std::unique_ptr loaded;
+ {
+ std::ifstream is(testfile, std::ios::binary);
+ boost::archive::polymorphic_binary_iarchive ia(is);
+ boost::archive::polymorphic_iarchive & pia = ia;
+ pia >> boost::serialization::make_nvp("ptr", loaded);
+ }
+
+ BOOST_CHECK(0 != loaded.get());
+ // the object recovered through the base pointer must be the derived type
+ BOOST_CHECK(0 != dynamic_cast(loaded.get()));
+
+ std::remove(testfile);
+ return EXIT_SUCCESS;
+}
+
+#else
+
+int test_main(int /* argc */, char * /* argv */ []){
+ return EXIT_SUCCESS;
+}
+
+#endif // BOOST_NO_CXX11_SMART_PTR