Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Aug 2023 09:47:32 +0300
From:      Konstantin Belousov <kostikbel@gmail.com>
To:        Dimitry Andric <dim@freebsd.org>
Cc:        Christoph Moench-Tegeder <cmt@burggraben.net>, Mark Millard <marklmi@yahoo.com>, toolchain@freebsd.org
Subject:   Re: c++: dynamic_cast woes
Message-ID:  <ZNXZhInNaBie9YHd@kib.kiev.ua>
In-Reply-To: <2AEA9921-5943-475C-B307-C5020BBE3F32@FreeBSD.org>
References:  <ZNATMN6sbaxcqE6n@elch.exwg.net> <E0109064-9ED3-483F-A7D9-6588EC07BF1F@yahoo.com> <6B6A7C9C-8F82-443D-BBC3-B2263FEAFD79@FreeBSD.org> <ZNLBwvwFMdo22k-3@elch.exwg.net> <6E31D6F9-8E9D-42FE-9D14-2A80EBD2B912@FreeBSD.org> <2AEA9921-5943-475C-B307-C5020BBE3F32@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, Aug 10, 2023 at 07:38:26PM +0200, Dimitry Andric wrote:
> On 10 Aug 2023, at 00:25, Dimitry Andric <dim@FreeBSD.org> wrote:
> > 
> > On 9 Aug 2023, at 00:29, Christoph Moench-Tegeder <cmt@burggraben.net> wrote:
> >> 
> >> ## Dimitry Andric (dim@FreeBSD.org):
> >> 
> >>> Yes, this is a typical problem when type info is replicated across
> >>> dynamic library boundaries. The best thing to prevent this is to
> >>> ensure that the key functions for a class (typically constructors
> >>> and destructors) are only in one translation unit (object file),
> >>> and that object file is only in one .so file.
> >> 
> >> As FreeBSD is basically unsupported from upstream, this sounds
> >> like I'm in for quite a bit of fun here. Well.
> > 
> > FWIW, it took quite a while (kicad has LOTS of dependencies!), but I
> > built kicad and it looks like I can reproduce the original problem,
> > after disabling the static-cast-patch. So I will investigate it a bit
> > further.
> 
> It looks like KiCad is violating the One Definition Rule (ODR) all over
> the place... So it will not really be trivial to fix, unfortunately.
> 
> The problem is that C++ virtual tables and type information gets copied
> into *both* the kicad main binaries (kicad/kicad-cli), and the plugins
> (_*.kiface). This is due to the way the binaries and plugins get linked,
> namely to a bunch of static libraries containing the common kicad parts
> (libcommon.a, libscripting.a, etc).
> 
> Classes like KICAD_SETTINGS or JOB_EXPORT_SCH_PDF are declared in header
> files, and usually their vtables and type_info get emitted into one
> particular object file, so for instance the vtable and type_info for
> KICAD_SETTINGS gets emitted into kicad_settings.cpp.o.
> 
> However, kicad_settings.cpp.o gets archived into libcommon.a, and this
> libcommon.a gets linked into both the main binaries *and* the .kiface
> plugins! It means there are now multiple copies of the same virtual
> table and type_info, and that is an explicit violation of the ODR.
> 
> The behavior at runtime is now officially undefined, but in practice it
> is implementation-defined: some implementations like libstdc++ work
> around it, by doing a deep comparison of type_info when casting
> dynamically. Others, like libcxxrt and libc++abi, only compare the
> addresses of the different copies of the same type_info, and in such
> cases the comparison will fail.
> 
> The correct way to fix this is by making sure the common code gets put
> into one shared libary, which explicitly exports all the required
> symbols (so using __dllexport on Windows, and non-hidden visibility on
> ELF platforms). Only then can you make sure the ODR is not violated.
> 
> But this would entail a pretty big refactoring for KiCad... :)
There is some GNU hack called STB_GNU_UNIQUE, which was made to handle
this kind of mess.  Or if you prefer, to make this mess even more tangled.
The https://gcc.gnu.org/legacy-ml/gcc-patches/2009-07/msg01240.html
is probably the best available documentation.

I am not sure if our rtld should handle the attribute.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?ZNXZhInNaBie9YHd>