From nobody Fri Apr 15 17:55:28 2022 X-Original-To: freebsd-hackers@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 9925C5D3625 for ; Fri, 15 Apr 2022 17:55:42 +0000 (UTC) (envelope-from marklmi@yahoo.com) Received: from sonic307-55.consmr.mail.gq1.yahoo.com (sonic307-55.consmr.mail.gq1.yahoo.com [98.137.64.31]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 4Kg3s91vyGz3tKC for ; Fri, 15 Apr 2022 17:55:41 +0000 (UTC) (envelope-from marklmi@yahoo.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1650045332; bh=nmdqiROzj6hr55xzKmJ4BWJVOFvUGiayDGjzuYWR3lA=; h=From:Subject:Date:References:To:In-Reply-To:From:Subject:Reply-To; b=P+VZdr3d8Jn4HW3lJsx3fzke5vT7uHxfT6Hb+RHwUJWygUYWB6JriTWLerm/U4waEf0ShMg97Wn0989RTlGip6b0SS7EXa+/mvKwgbpC03K3ABmszBvFGZICJ/caG/A9ph6OB5Ze7Ytp0UJW8gJgmYyPzK4GOjXBminkwcXMMI61NSVAzUxXaqqWRCJIaGU/MH61ead7nDgbowd9XrZ4OeK5YFTUxrpBVJ91sC5wld9GLn/QIDsaewSs/JbCNr0igXLed15hQ0ZV0zYhIj+sNaFjp6NZt6bE+Rp0xMl/7ClzFA1zbBZh57Do8dTxEPkQr9wL2hTy33oc5SvfT83bCw== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1650045332; bh=unXWOnsoBL1Nu2s2UuckqCdyQ5S40oOL+kXGy4kujab=; h=X-Sonic-MF:From:Subject:Date:To:From:Subject; b=OoxS+1Sm7i5ioSeFcWnNElDCem1sr+na/ImHux2FRjDZzM3pLr4+Q/768eTgES3oQ5pYADwjrJpjqAbb0coyoZIGzr8ek9NXSrqac9biAE5NN4vfEtYOQygcD7MaIdkMQHl+oGLuSFoq8TNRxZkaVwKjCuaE+lPJy3cF5Ms8wT1Padk8oYC9HQkELJh51tqlnggOKTQDQKTStS3o46JNU7tz2ej1aI26ovXXl1nPsK/Mp+2y/N85j3nsrfGxtxAzB9T503ipnRHqRoFNZc2QkitTVjXKiJlrH/r8YRZ5PkvcVig9fCZa4QRY95PqCVeeM2UJdAcUqzV+PvBQNF6ThA== X-YMail-OSG: zvAN4eYVM1nEW4rJrWx7TUoYHCuh0brVcwmO.kHUwRqK1nAYkiFGpWvqJX74EhG KBI.eQ5Ctk7RB1oTzZwWXDHZKLvMyD9NQYpbL04.VUU2rh5YnRQed0bGxyn_nbd6oxm0mg.vjLle cejchiZSvbZGqADBDrdAz0h90pp6J3YLnwDo4lcOyqtFXPYeiXiSaFe.HToNOhvjYIvnpQA_Jjqf 3N.9lB0cK2gEgN51nr6qE5NqXFc_Mp4.BCvWokblSRXMDq_EtXiRo1INz1dR_BkludRHZHArCbf7 OowC0A5eGstZrLs3ARvBQ1rLJPjzve2H9jzSQWLTdp.WdzWOKZapONAo16A9784hLMo8tOvGMiCg apN4V_jobOGh2eJtt.SarEhaYUUerIfmwruKzyDNyMTx5WzhdabKGcaKPZGxFF7O1yw5j_A1rTpJ IAT8L1HDnJhgPJ2x2Ixdi.lfMgfaFXCrdXB3wvGqe8y_FWacxKSO3UmpTfHxZc0F3yGD2bVJyPQP mnwFJRN4_r5XSLMxIPYacDqSSbL2zbfiSg2Lcczyedf19lfIdk1TDnPF.xgI8UYXj.b.CzJX9dsS awjNBBwPT3s95wDD_LsPQWYv8rNvbZEQZ_LvQEpwP86i8rS60ETWtuLX4VFGeSLW4MeyqJdWddQn K6pEg8NjNk8eolVfI5Q.RSA2LzaGkxtoleAiiKiz.XZGa.jwT1ik9XC4Y2FdkK2QeUw2j3zPjo8M Ppsi.IpHRJ9EJDN9Ntli4KelX3RhpuQgJfVeQT2qt3XbC3hUG5jbw1YtogHBQsnPOWuQtWhT_RCI 2bNAx.9UPk97V._yVTo7fduLCt8OweHqiv675D8YwoETqNjM0CgxP3FdUgtHdK7iNDTSCWYlQvL. 0jgzwjWK_0MsmtZXzEQcg_g8z0f5rAPnGvDR1rMT9OB_fzybIZGSbzC9xr191txP_vwwLE7BjZjW qlbA8OXtNa5QOOmXZn7sQrVmpIYCMGxe90BCIhusRxPy8zGxYMCZhHWfFKK3KEssscbAj9O7.zV9 xvN.0sj56wVR5NryNB8JyG4ox1GYCNYGj4KWuPgKXy2JEx7A1GVPmR6BWbVttBWuiL1.ax6DNPe4 R1y_b6T4p2kdPi09JXLgZOPljuFaPRkKYjQgH2cBCSvxlN3Vt2rB17f.xMHgW73TmxGdKeADWtix 72ro1qlraboLH3AwYLwXPeHdwEexYkaSKqhLH0bBdTltwcfEx4Qfpeh2bWpZrz7a9CpKQ4940DQd c4qNfg2nYOwiKFA2xrsRQr60cxKNDlXrX5UECVSxC6p0xsxNnXo8sz10LcNZWMLhzN1MKT0uy5L6 FoowV_X4FzVi6rekbZEEQi8M83gpp0XWbbmhjg.Rs70c0suRyKSHwMJW5PFe0rWEXoiCuRhVHnxK 7oYJLHbk2t1fYp93YjeXEnNoLkH0Vv4gKsiUoijfhWWwKTieR7_LHwft.mbYjiFWGpbHDZwVXC53 e4blCUJfGuljoCJXCpoQNhRqsG5RW7soBJz1uGZm_.4nEliCjhpR2bfZqbI9LJcS9EGAtI6HwNHc DDgUrWCimwDyX05ZhGGD1T2SlEwuA6XEu_wCwoWs._m9dW09jlpwLUZxFaX7dTSK_hIbrO.HYXZS ua1mSTQuGSy6gxKQc8ngjUrkXOJT2qww5IQHt.r_EYv7VipYaF7715wda4HDJ52GMc9VB5nIADSK ghOPbKWESkdtObTmHDPx03wUOJOsM7Uf75ajFDD9XJh_.adkcvIjTEaj57fZe7.2g5TlVXB4leW2 fPGKgSSyqqGkk7q0b4nQoIkfPal3Jpcuer4mc2cIac1f_2.qrEqCjLgFreieddl_Usl3k6T2G83m 8_z0Wt25tyn9qsIJAE4hWEVBaae7fZtP5EQzVy31leU0eUstU7F9n_ogLpLeVUbD4z4hvxlaklU5 i0gfyDdwGebaKwOO8Cq.UIuKNHSeCVy_ynIG9QuxAvnRL1_PmXhL2Hxg7nvmoWsxEqxiLv_jt.qE oF.39szUWPRsEo0SSFTKaLQEcLbJD4juY.X2a9pgCqyvvAJzsAgCd.SPX0r7Ew.P6kLkSKnyUQcQ QacVh0TTPbVtIWfqqAgeKla1w58HyGC_8Ad4OR7THyheJqn4wo8U45M3eF6eOtdoWVW6aBjrPxTv pCFHuGTy8iBebS2E2LTqHgAs.8FzjFl5rETiN7a6ndwRs.7LfHHkGCg7SKxSaYgA_9N2vvpVdnf_ pxdZDLb3L6.MK3gCesXVqoYR28EKA73ef6M7tfme.zUjofftSm0k.nBisxIx4brsNT5Y4_KnX8HU SIu_cwHbANQ-- X-Sonic-MF: Received: from sonic.gate.mail.ne1.yahoo.com by sonic307.consmr.mail.gq1.yahoo.com with HTTP; Fri, 15 Apr 2022 17:55:32 +0000 Received: by hermes--canary-production-ne1-c7c4f6977-g2rrz (VZM Hermes SMTP Server) with ESMTPA ID 05999a92e1a5a9887187640452537f02; Fri, 15 Apr 2022 17:55:30 +0000 (UTC) From: Mark Millard Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable List-Id: Technical discussions relating to FreeBSD List-Archive: https://lists.freebsd.org/archives/freebsd-hackers List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-freebsd-hackers@freebsd.org Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.13\)) Subject: Re: llvm & RTTI over shared libraries Date: Fri, 15 Apr 2022 10:55:28 -0700 References: <9ADA04B1-2A0F-4B96-8510-88A5E4E1E2C0@yahoo.com> To: jbo@insane.engineer, FreeBSD Hackers In-Reply-To: <9ADA04B1-2A0F-4B96-8510-88A5E4E1E2C0@yahoo.com> Message-Id: <77054BF9-54C0-4325-BE6F-66A5F04474CF@yahoo.com> X-Mailer: Apple Mail (2.3654.120.0.1.13) X-Rspamd-Queue-Id: 4Kg3s91vyGz3tKC X-Spamd-Bar: - Authentication-Results: mx1.freebsd.org; dkim=pass header.d=yahoo.com header.s=s2048 header.b=P+VZdr3d; dmarc=pass (policy=reject) header.from=yahoo.com; spf=pass (mx1.freebsd.org: domain of marklmi@yahoo.com designates 98.137.64.31 as permitted sender) smtp.mailfrom=marklmi@yahoo.com X-Spamd-Result: default: False [-1.50 / 15.00]; TO_DN_SOME(0.00)[]; FREEMAIL_FROM(0.00)[yahoo.com]; MV_CASE(0.50)[]; R_SPF_ALLOW(-0.20)[+ptr:yahoo.com]; DKIM_TRACE(0.00)[yahoo.com:+]; RCPT_COUNT_TWO(0.00)[2]; DMARC_POLICY_ALLOW(-0.50)[yahoo.com,reject]; FROM_EQ_ENVFROM(0.00)[]; RCVD_TLS_LAST(0.00)[]; MIME_TRACE(0.00)[0:+]; FREEMAIL_ENVFROM(0.00)[yahoo.com]; ASN(0.00)[asn:36647, ipnet:98.137.64.0/20, country:US]; MID_RHS_MATCH_FROM(0.00)[]; DWL_DNSWL_NONE(0.00)[yahoo.com:dkim]; ARC_NA(0.00)[]; NEURAL_HAM_MEDIUM(-1.00)[-1.000]; R_DKIM_ALLOW(-0.20)[yahoo.com:s=s2048]; FROM_HAS_DN(0.00)[]; NEURAL_SPAM_SHORT(1.00)[0.999]; NEURAL_HAM_LONG(-1.00)[-1.000]; MIME_GOOD(-0.10)[text/plain]; TO_MATCH_ENVRCPT_SOME(0.00)[]; RCVD_IN_DNSWL_NONE(0.00)[98.137.64.31:from]; MLMMJ_DEST(0.00)[freebsd-hackers]; RWL_MAILSPIKE_POSSIBLE(0.00)[98.137.64.31:from]; RCVD_COUNT_TWO(0.00)[2] X-ThisMailContainsUnwantedMimeParts: N On 2022-Apr-14, at 23:25, Mark Millard wrote: > From: wrote on > Date: Thu, 14 Apr 2022 16:36:24 +0000 : > (I've line-split the text.) >=20 >> I'm in the middle of moving to FreeBSD as my primary development = platform (desktop wise). >> As such, I am currently building various software tools I've written = over the years on >> FreeBSD for the first time. Most of those were developed on either = Linux+GCC or on >> Windows+Mingw (MinGW -> GCC). >>=20 >> Today I found myself debugging a piece of software which runs fine on = FreeBSD when >> compiled with gcc11 but not so much when compiling with clang14. >> I managed to track down the problem but I lack the deeper = understanding to resolve >> this properly - so here we are. >>=20 >> The software in question is written in C++20 and consisting of: >> - An interface library (just a bunch of header files). >> - A main executable. >> - A bunch of plugins which the executable loads via dlopen(). >>=20 >> The interface headers provide several types. Lets call them A, B, C = and D. where B, >> C and D inherit from A. >> The plugins use std::dynamic_pointer_cast() to cast an = std::shared_ptr (received >> via the plugin interface) to the derived classes such as = std::shared_ptr. >> This is where the trouble begins. >>=20 >> If everything (the main executable and the plugins) are compiled = using gcc11, everything >> works "as I expect it". >> However, when compiling everything with clang14, the main executable = is able to load the >> plugins successfully but those std::dynamic_pointer_cast() calls = within the plugins >> always return nullptr. >>=20 >> After some research I seem to understand that the way that RTTI is = handled over shared >> library boundaries is different between GCC and LLVM. >> This is where my understanding starts to get less solid. >>=20 >> I read the manual page of dlopen(3). It would seem like the flag = RTLD_GLOBAL would be >> potentially interesting to me: "Symbols from this shared object [...] = of needed objects >> will be available for re-solving undefined references from all other = shared objects." >> The software (which "works as intended" when compiled with GCC) was = so far only calling >> dlopen(..., RTLD_LAZY). >> I'm not even sure whether this applies to my situation. My gut = feeling tells me that I'm >> heading down the wrong direction here. After all, the main executable = is able to load >> the plugins and to call the plugin's function which receives an = std::shared_ptr >> asparameter just fine, also when compiled with LLVM. >> Is the problem I'm experiencing related to the way that the plugin = (shared library) is >> loaded or the way that the symbols are being exported? >> In the current state, the plugins do not explicitly export any = symbols. >>=20 >> Here's a heavily simplified version of my scenario: >=20 > The simplified example was not designed to compile and test. > So I made guesses and made my own. The .cpp files have > comments on the compile/link commands used and there are > examples of c++ and g++11 compile/link/run sequences > after the source code. The code is not well commented. Nor > does it deal with error handling or the like. But it is > fairly short overall. >=20 > # more base_plugin.h > #include >=20 > // For its own libbase_plugin.so file, load time bound, no dlopen used = for it: >=20 > struct base > { > virtual ~base(); > }; > struct base_plugin > { > virtual std::shared_ptr create_data_instance() = =3D 0; > virtual void action(std::shared_ptr = data) =3D 0; > virtual ~base_plugin(); > }; >=20 > extern "C" // for each derived plugin .so file: > { > using plugin_instance_creator=3D base_plugin* (*)(); > const char plugin_instance_creator_name[] =3D = "create_plugin_instance"; // Lookup via dlsym. >=20 > using plugin_instance_destroyer=3D void (*)(base_plugin*); > const char plugin_instance_destroyer_name[] =3D = "destroy_plugin_instance"; // Lookup via dlsym. > }; >=20 > # more base_plugin.cpp > // c++ -std=3Dc++20 -O0 -g -fPIC -lc++ -olibbase_plugin.so = -shared base_plugin.cpp > // g++11 -std=3Dc++20 -O0 -g -fPIC -lstdc++ -olibbase_plugin.so = -shared base_plugin.cpp >=20 > #include "base_plugin.h" >=20 > base::~base() {} > base_plugin::~base_plugin() {} >=20 > # more main_using_plugin.cpp=20 > // c++ -std=3Dc++20 -O0 -g -fPIC -lc++ -L. -lbase_plugin = -Wl,-rpath=3D. \ > // -omain_using_plugin = main_using_plugin.cpp > // g++11 -std=3Dc++20 -O0 -g -fPIC -lstdc++ -L. -lbase_plugin = -Wl,-rpath=3D. \ > // -Wl,-rpath=3D/usr/local/lib/gcc11 -omain_using_plugin = main_using_plugin.cpp >=20 > #include "base_plugin.h" > #include >=20 > int main() > { > auto dl=3D dlopen("./libsharedlib_plugin.so",RTLD_LAZY); // = hardcoded .so path for the example >=20 > union { void* as_voidptr; plugin_instance_creator = as_plugin_instance_creator; } creator_plugin_func; > creator_plugin_func.as_voidptr=3D = dlsym(dl,plugin_instance_creator_name); >=20 > union { void* as_voidptr; plugin_instance_destroyer = as_plugin_instance_destroyer; } destroyer_plugin_func; > destroyer_plugin_func.as_voidptr=3D = dlsym(dl,plugin_instance_destroyer_name); >=20 > auto plugin=3D = (creator_plugin_func.as_plugin_instance_creator)(); >=20 > { // Local scope for data > std::shared_ptr = data{plugin->create_data_instance()}; > plugin->action(data); > } // Presume for the example that nothing requires the plugin = after here. >=20 > (destroyer_plugin_func.as_plugin_instance_destroyer)(plugin); > destroyer_plugin_func.as_voidptr=3D nullptr; >=20 > dlclose(dl); > } >=20 > NOTE: So, other than the dlopen, the above has no direct tie to > the specific dynamically loaded plugin. The base_plugin is in a > .so but is load-time bound instead of using dlopen. That .so > would be used by all the plugins found via dllopen. (I only > made one example.) >=20 > As for the .so used via dlopen/dlsym/dlclose . . . >=20 > # more sharedlib_plugin.h > #include "base_plugin.h" >=20 > // For its own libsharedlib_plugin.so file, where dlopen is used to = find it: >=20 > struct sharedlib : base { int v; }; > struct sharedlib_plugin : base_plugin > { > std::shared_ptr create_data_instance() = override; > void action(std::shared_ptr base) = override; > }; >=20 > # more sharedlib_plugin.cpp > // c++ -std=3Dc++20 -O0 -g -fPIC -lc++ -olibsharedlib_plugin.so = -shared sharedlib_plugin.cpp > // g++11 -std=3Dc++20 -O0 -g -fPIC -lstdc++ -olibsharedlib_plugin.so = -shared sharedlib_plugin.cpp >=20 > #include "sharedlib_plugin.h" > #include >=20 > std::shared_ptr sharedlib_plugin::create_data_instance() > { > std::cout << "create_data_instance in use from dlopen'd .so\n"; > return = std::static_pointer_cast(std::make_shared()); > } >=20 > void sharedlib_plugin::action(std::shared_ptr b) > { > std::cout << "action in use from dlopen'd .so class\n"; > auto separate_share =3D = std::dynamic_pointer_cast(b); > if (separate_share->v || 1 < separate_share.use_count()) > std::cout << "separate_share is not nullptr (would = crash otherwise)\n"; > } >=20 > extern "C" base_plugin* create_plugin_instance() > { > std::cout << "create_plugin_instance in use from dlopen'd = .so\n"; > return new sharedlib_plugin(); > } >=20 > extern "C" void destroy_plugin_instance(const base_plugin* plugin) > { > std::cout << "destroy_plugin_instance in use from dlopen'd = .so\n"; > delete plugin; > } >=20 > # c++ -std=3Dc++20 -O0 -g -fPIC -lc++ -olibbase_plugin.so -shared = base_plugin.cpp > # c++ -std=3Dc++20 -O0 -g -fPIC -lc++ -L. -lbase_plugin -Wl,-rpath=3D. = \ > -omain_using_plugin main_using_plugin.cpp > # c++ -std=3Dc++20 -O0 -g -fPIC -lc++ -olibsharedlib_plugin.so -shared = sharedlib_plugin.cpp > # ./main_using_plugin > create_plugin_instance in use from dlopen'd .so > create_data_instance in use from dlopen'd .so > action in use from dlopen'd .so class > separate_share is not nullptr (would crash otherwise) > destroy_plugin_instance in use from dlopen'd .so >=20 > For reference: >=20 > # ldd main_using_plugin > main_using_plugin: > libc++.so.1 =3D> /lib/libc++.so.1 (0x819d0000) > libcxxrt.so.1 =3D> /lib/libcxxrt.so.1 (0x82735000) > libbase_plugin.so =3D> ./libbase_plugin.so (0x8328d000) > libm.so.5 =3D> /lib/libm.so.5 (0x83c47000) > libgcc_s.so.1 =3D> /lib/libgcc_s.so.1 (0x85861000) > libc.so.7 =3D> /lib/libc.so.7 (0x848f9000) >=20 > # ldd ./libsharedlib_plugin.so > ./libsharedlib_plugin.so: > libc++.so.1 =3D> /lib/libc++.so.1 (0x3b69aeeb6000) > libcxxrt.so.1 =3D> /lib/libcxxrt.so.1 (0x3b69af6f2000) > libm.so.5 =3D> /lib/libm.so.5 (0x3b69afd1f000) > libgcc_s.so.1 =3D> /lib/libgcc_s.so.1 (0x3b69b0303000) > libc.so.7 =3D> /lib/libc.so.7 (0x3b69aafdb000) >=20 >=20 > As for g++11 use . . . >=20 > Testing with g++11 does involve additional/adjusted command line > options: > -Wl,-rpath=3D/usr/local/lib/gcc11/ ( for main_using_plugin.cpp ) > -lstdc++ (for all 3 .cpp files) >=20 > (FreeBSD's libgcc_s.so.1 does not cover everything needed for > all architectures for g++11's code generation. I was working > in a context where using /usr/local/lib/gcc11//libgcc_s.so.1 > was important.) >=20 >=20 > # g++11 -std=3Dc++20 -O0 -g -fPIC -lstdc++ -olibbase_plugin.so -shared = base_plugin.cpp > # g++11 -std=3Dc++20 -O0 -g -fPIC -lstdc++ -L. -lbase_plugin = -Wl,-rpath=3D. \ > -Wl,-rpath=3D/usr/local/lib/gcc11 -omain_using_plugin = main_using_plugin.cpp > # g++11 -std=3Dc++20 -O0 -g -fPIC -lstdc++ -olibsharedlib_plugin.so = -shared sharedlib_plugin.cpp > # ./main_using_plugin > create_plugin_instance in use from dlopen'd .so > create_data_instance in use from dlopen'd .so > action in use from dlopen'd .so class > separate_share is not nullptr (would crash otherwise) > destroy_plugin_instance in use from dlopen'd .so >=20 > For reference: >=20 > # ldd main_using_plugin > main_using_plugin: > libstdc++.so.6 =3D> /usr/local/lib/gcc11//libstdc++.so.6 = (0x83a00000) > libbase_plugin.so =3D> ./libbase_plugin.so (0x8213d000) > libm.so.5 =3D> /lib/libm.so.5 (0x82207000) > libgcc_s.so.1 =3D> /usr/local/lib/gcc11//libgcc_s.so.1 = (0x82c66000) > libc.so.7 =3D> /lib/libc.so.7 (0x849c4000) >=20 > # ldd ./libsharedlib_plugin.so > ./libsharedlib_plugin.so: > libstdc++.so.6 =3D> /usr/local/lib/gcc11/libstdc++.so.6 = (0x1c2a7b800000) > libm.so.5 =3D> /lib/libm.so.5 (0x1c2a7bb1c000) > libgcc_s.so.1 =3D> /lib/libgcc_s.so.1 (0x1c2a7c416000) > libc.so.7 =3D> /lib/libc.so.7 (0x1c2a780e8000) >=20 >=20 > Overall: >=20 > Looks to me like both the system clang/llvm and g++11 contexts > are working. (The platform context was aarch64 main [so: 14], > in case it matters.) It also works for clang++14 from devel/llvm14 : # clang++14 -std=3Dc++20 -O0 -g -fPIC -lc++ -olibbase_plugin.so -shared = base_plugin.cpp # clang++14 -std=3Dc++20 -O0 -g -fPIC -lc++ -L. -lbase_plugin = -Wl,-rpath=3D. -omain_using_plugin main_using_plugin.cpp # clang++14 -std=3Dc++20 -O0 -g -fPIC -lc++ -olibsharedlib_plugin.so = -shared sharedlib_plugin.cpp # ./main_using_plugin create_plugin_instance in use from dlopen'd .so create_data_instance in use from dlopen'd .so action in use from dlopen'd .so class separate_share is not nullptr (would crash otherwise) destroy_plugin_instance in use from dlopen'd .so # ldd main_using_plugin main_using_plugin: libc++.so.1 =3D> /lib/libc++.so.1 (0x81ceb000) libcxxrt.so.1 =3D> /lib/libcxxrt.so.1 (0x82a4f000) libbase_plugin.so =3D> ./libbase_plugin.so (0x833a5000) libm.so.5 =3D> /lib/libm.so.5 (0x84fcb000) libgcc_s.so.1 =3D> /lib/libgcc_s.so.1 (0x83b37000) libc.so.7 =3D> /lib/libc.so.7 (0x84739000) # ldd ./libsharedlib_plugin.so ./libsharedlib_plugin.so: libc++.so.1 =3D> /lib/libc++.so.1 (0x2a87e9ab1000) libcxxrt.so.1 =3D> /lib/libcxxrt.so.1 (0x2a87e86dc000) libm.so.5 =3D> /lib/libm.so.5 (0x2a87e9020000) libgcc_s.so.1 =3D> /lib/libgcc_s.so.1 (0x2a87eace1000) libc.so.7 =3D> /lib/libc.so.7 (0x2a87e45a9000) I've also used -O2 and lack of -g . All the combinations I tried worked. =3D=3D=3D Mark Millard marklmi at yahoo.com