On Mon, 13 Feb 2023 at 19:49, Adhemerval Zanella Netto
<adhemerval.zane...@linaro.org> wrote:
>
>
>
> On 13/02/23 12:49, Bartosz Golaszewski wrote:
> > Hey!
> >
> > I'm the author and maintainer of libgpiod. I'm currently getting ready
> > to do a new major release. After giving some exposure to the release
> > candidate, I noticed that when using clang, I can't link against the
> > C++ bindings, while it works just fine in GCC.
> >
> > The tree in question is here:
> > https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/log/
> >
> > You can trigger the linking program by trying to build the C++ tests
> > with clang like that:
> >
> > CC=clang CXX=clang++ ./autogen.sh --enable-bindings-cxx --enable-tests
> > && make -j16
> >
> > You'll get the following error:
> >
> > /usr/bin/ld: tests-chip.o:(.data+0x0): undefined reference to
> > `typeinfo for gpiod::chip_closed'
> > /usr/bin/ld: tests-line-request.o:(.data+0x0): undefined reference to
> > `typeinfo for gpiod::request_released'
> > /usr/bin/ld: .libs/gpiod-cxx-test: hidden symbol
> > `_ZTIN5gpiod11chip_closedE' isn't defined
> > /usr/bin/ld: final link failed: bad value
> >
> > The typoinfo is missing for exception types that should be visible to
> > users of the library.
> >
> > The culprit is here:
> > https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/bindings/cxx/gpiod.hpp#n26
> >
> > I added the GPIOD_CXX_BUILD macro in order to not re-export the
> > visible symbols if any user of the library would include the gpiod.hpp
> > header. When the library is being built, the symbols are visible, when
> > someone includes the header, the symbols are hidden.
>
> But the typeid of the symbol, for instance gpiod, will still be provided
> by shared library if I understood correctly:
>
> libgpiod-llvm$ objdump -t ./bindings/cxx/tests/tests-chip.o 2>/dev/null| grep 
> -w _ZTIN5gpiod11chip_closedE
> 0000000000000000         *UND*  0000000000000000 .hidden 
> _ZTIN5gpiod11chip_closedE
> libgpiod-llvm$ objdump -t bindings/cxx/.libs/libgpiodcxx.so 2>/dev/null| grep 
> _ZTIN5gpiod11chip_closedE
> 0000000000024b50 g     O .data.rel.ro   0000000000000018              
> _ZTIN5gpiod11chip_closedE
>
> However, it seems that GCC is not applying the hidden attribute on the
> typeid class:
>
> libgpiod-gcc$ objdump -t ./bindings/cxx/tests/tests-chip.o 2>/dev/null| grep 
> -w _ZTIN5gpiod11chip_closedE
> 0000000000000000  w    O .data.rel.local.DW.ref._ZTIN5gpiod11chip_closedE     
>   0000000000000008 .hidden DW.ref._ZTIN5gpiod11chip_closedE
> 0000000000000000         *UND*  0000000000000000 _ZTIN5gpiod11chip_closedE
>
> When it creates create the vague linking weak symbol
> .data.rel.local.DW.ref._ZTIN5gpiod11chip_closedE.
>
> I am not sure why GCC is being permissive here, in fact IMHO this is
> gcc issue. If I add the visibility explicitly using pragmas:
>
> diff --git a/bindings/cxx/gpiodcxx/exception.hpp 
> b/bindings/cxx/gpiodcxx/exception.hpp
> index 98b7bc4..24ae698 100644
> --- a/bindings/cxx/gpiodcxx/exception.hpp
> +++ b/bindings/cxx/gpiodcxx/exception.hpp
> @@ -17,6 +17,8 @@
>
>  namespace gpiod {
>
> +#pragma GCC visibility push(hidden)
> +
>  /**
>   * @ingroup gpiod_cxx
>   * @{
> @@ -25,7 +27,7 @@ namespace gpiod {
>  /**
>   * @brief Exception thrown when an already closed chip is used.
>   */
> -class GPIOD_CXX_API chip_closed : public ::std::logic_error
> +class /*GPIOD_CXX_API*/ chip_closed : public ::std::logic_error
>  {
>  public:
>
> @@ -64,6 +66,8 @@ public:
>         virtual ~chip_closed();
>  };
>
> +#pragma GCC visibility pop
> +
>  /**
>   * @brief Exception thrown when an already released line request is used.
>   */
>
> I get an explicit linking error:
>
> /usr/bin/ld: 
> tests-chip.o:(.data.rel.local.DW.ref._ZTIN5gpiod11chip_closedE[DW.ref._ZTIN5gpiod11chip_closedE]+0x0):
>  undefined reference to `typeinfo for gpiod::chip_closed'
>
> Which is what I expect.  So I suggest you to avoid adding the hidden
> visibility on tests because since there are not linking static, they
> should follow the default rules of ABI and hidden in this case does
> not really make much sense.
>

I'm not sure I understand this. The tests are linked dynamically -
just like any other program would. IIUC: I build libgpiodcxx making
the exception symbols visible, then if anyone else (a program linking
against libgpiodcxx) includes the header, the symbol is hidden.

On top of that - if I build the examples with clang, they build
because they don't reference the symbols openly. But if I then make
one of those exceptions fly out of libgpiod unconditionally, their
typeid is correctly seen:

terminate called after throwing an instance of 'gpiod::request_released'
  what():  GPIO lines have been released
Aborted

If on the other hand I add catch (const gpiod::request_released& ex)
somewhere, I get the same linking error.

The same happens for any program that I'd build with -llgpiodcxx

Bart

> >
> > If I make the symbols unconditionally visible here, clang starts to
> > work but I have no idea why and would like to avoid re-exporting the
> > symbols if I can.
> >
> > I'm using the following version:
> > Ubuntu clang version 15.0.6
> > Target: x86_64-pc-linux-gnu
> > Thread model: posix
> > InstalledDir: /usr/bin
> >
> > Host is: x86_64 GNU/Linux
> >
> > It's not like gcc links fine but then fails to obtain typeid - I can
> > catch exceptions coming out from libgpiod just fine in external apps
> > linked using gcc and see their type.
> >
> > Any hints?
>
>
_______________________________________________
linaro-toolchain mailing list -- linaro-toolchain@lists.linaro.org
To unsubscribe send an email to linaro-toolchain-le...@lists.linaro.org

Reply via email to