Ipiano
Ipiano

Reputation: 269

GCC plugin fails to resolve `json::integer_number` symbol in Yocto SDK

Scenario

I have a Yocto Kirkstone Aarch64 SDK containing GCC 11.5, and I would like to build something with a GCC plugin using that SDK. I have compiled the plugin, and attempting to use it yields

error: symbol lookup error: undefined symbol: _ZTVN4json14integer_numberE (fatal)

Background

This SDK is being produced along with a full embedded linux image, which I have the ability to modify. However, I would like to be able to build plugins and use them with the SDK without having to modify the layers of the build.

I have validated that this same plugin can be built, and used, with GCC 11.4 and 12.3 on my host system (Ubuntu 22.04.5)

Build Process

The project in question is https://github.com/royjacobson/externis. This project does not natively support a "cross-compilation" sort of usage, but I've modified it locally such that I can override the GCC plugin include directory - building with something like

cmake -DGCC_PLUGIN_INCLUDE=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/usr/lib/aarch64-poky-linux/gcc/aarch64-poky-linux/11.5.0/plugin

Note - this is done using my host system's compiler; I am not using the SDK tooling to build the plugin.

The plugin header is present, and it builds just fine. I can install the plugin to that directory, and pass -fplugin=externis to GCC while using the SDK's environment to activate the plugin; however, when cc1plus attempts to load it, symbols fail to resolve.

Investigation So Far

My initial thought was to validate that the symbols exist somewhere at all - this has been validated. I'm no expert on the GCC plugin infrastructure, but as far as I can tell, the symbols are built into cc1plus directly, and then resolve from there during a dlopen call for the plugin being loaded. See https://github.com/gcc-mirror/gcc/blob/master/gcc/plugin.cc#L705

Using readelf, I have observed that these symbols are present both in my host cc1plus and the cross-canadian one in the SDK

$ readelf -aW /lib/gcc/x86_64-linux-gnu/12/cc1plus | grep _ZTVN4json14integer_numberE
 13196: 0000000002345d70    48 OBJECT  WEAK   DEFAULT   18 _ZTVN4json14integer_numberE

$ readelf -aW /opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/usr/libexec/aarch64-poky-linux/gcc/aarch64-poky-linux/11.5.0/cc1plus | grep _ZTVN4json14integer_numberE
 29612: 0000000001a97e18    48 OBJECT  WEAK   DEFAULT   17 _ZTVN4json14integer_numberE

I've also attempted to build something using LD_DEBUG=all - and in this case, I can observe that my host's cc1plus provides this symbol, but for some reason the one in the toolchain doesn't. Below are the relevant sections of the output from ld

    218809: symbol=_ZTVN4json14integer_numberE;  lookup in file=/usr/lib/gcc/x86_64-linux-gnu/12/cc1plus [0]
    218809: binding file /usr/lib/gcc/x86_64-linux-gnu/12/plugin/externis.so [0] to /usr/lib/gcc/x86_64-linux-gnu/12/cc1plus [0]: normal symbol `_ZTVN4json14integer_numberE'
    218392: symbol=_ZTVN4json14integer_numberE;  lookup in file=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/usr/libexec/aarch64-poky-linux/gcc/aarch64-poky-linux/11.5.0/cc1plus [0]
    218392: symbol=_ZTVN4json14integer_numberE;  lookup in file=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/usr/libexec/aarch64-poky-linux/gcc/aarch64-poky-linux/11.5.0/../../../../../lib/libmpc.so.3 [0]
    218392: symbol=_ZTVN4json14integer_numberE;  lookup in file=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/usr/libexec/aarch64-poky-linux/gcc/aarch64-poky-linux/11.5.0/../../../../../lib/libmpfr.so.6 [0]
    218392: symbol=_ZTVN4json14integer_numberE;  lookup in file=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/usr/libexec/aarch64-poky-linux/gcc/aarch64-poky-linux/11.5.0/../../../../../lib/libgmp.so.10 [0]
    218392: symbol=_ZTVN4json14integer_numberE;  lookup in file=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/usr/libexec/aarch64-poky-linux/gcc/aarch64-poky-linux/11.5.0/../../../../../lib/libz.so.1 [0]
    218392: symbol=_ZTVN4json14integer_numberE;  lookup in file=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/usr/libexec/aarch64-poky-linux/gcc/aarch64-poky-linux/11.5.0/../../../../../lib/libzstd.so.1 [0]
    218392: symbol=_ZTVN4json14integer_numberE;  lookup in file=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/lib/libm.so.6 [0]
    218392: symbol=_ZTVN4json14integer_numberE;  lookup in file=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/lib/libc.so.6 [0]
    218392: symbol=_ZTVN4json14integer_numberE;  lookup in file=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/lib/ld-linux-x86-64.so.2 [0]
    218392: symbol=_ZTVN4json14integer_numberE;  lookup in file=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/lib/libpthread.so.0 [0]
    218392: symbol=_ZTVN4json14integer_numberE;  lookup in file=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/usr/lib/aarch64-poky-linux/gcc/aarch64-poky-linux/11.5.0/plugin/externis.so [0]
    218392: symbol=_ZTVN4json14integer_numberE;  lookup in file=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/usr/libexec/aarch64-poky-linux/gcc/aarch64-poky-linux/11.5.0/../../../../../lib/libstdc++.so.6 [0]
    218392: symbol=_ZTVN4json14integer_numberE;  lookup in file=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/lib/libgcc_s.so.1 [0]
    218392: symbol=_ZTVN4json14integer_numberE;  lookup in file=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/lib/libc.so.6 [0]
    218392: symbol=_ZTVN4json14integer_numberE;  lookup in file=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/lib/libm.so.6 [0]
    218392: symbol=_ZTVN4json14integer_numberE;  lookup in file=/opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/lib/ld-linux-x86-64.so.2 [0]
    218392: /opt/toolchains/kirkstone/aarch64/sysroots/x86_64-sdk-linux/usr/lib/aarch64-poky-linux/gcc/aarch64-poky-linux/11.5.0/plugin/externis.so: error: symbol lookup error: undefined symbol: _ZTVN4json14integer_numberE (fatal)

Hypotheses

The most obvious hypothesis here is that I just don't understand something about symbol tables and the symbols are either not present, partially present, or present but in some way that they don't match - maybe symbol versions are coming into play? But I would have expected symbol versions to manifest in the readelf output

Another likely option is that something about how GCC is being built is shooting this in the foot - I'm using --enable-plugin, and I've explicitly disabled stripping of the package; but I'm not going to rule out that something in the Yocto build process is still messing with the binary in a way that causes the symbols to not be valid.

I've also been looking into if I could/should add extra tooling in the SDK that can be used to build the plugin itself targeting the SDK.

The next thing I'm planning to attempt is just adding the plugin directly to the SDK - add a recipe to my Yocto build, package it up, etc. But I'd like to avoid that if possible as a long-term solution, or at the very least, I'm looking to understand what it is about my strategy isn't wrong.

Upvotes: 1

Views: 51

Answers (0)

Related Questions