4

I'm currently trying to link a Rust executable with a shared library written in C++ and C. The dynamic loading of the shared library works perfectly on amd64 architectures but I am running into segmentation fault errors when the executable tries to load the shared library on an aarch64 linux machine [Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-1033-raspi2 aarch64)].

I am using the Linaro aarch64 toolchain (http://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz) to cross-compile the shared library (combination of C++ and C code).

On inspection using file/readelf, the resultant shared library has the GNU/Linux ABI which seems to be because of the use of g++ to build the C++ code in the library whereas the ABI of the Rust executable is SYSV (cross compiled for aarch64 using the https://github.com/rust-embedded/cross project)

I’ve noticed that manually editing the .so file of the shared library to change the ABI flag from GNU/Linux to SYSV resolves the problem.

Is it possible to make either the executable or the library target a specific ABI? Ideally, I would like to build the Rust executable in a way so that it can link to the shared library irrespective of the library's ABI.

To provide a brief overview, the shared library is an implementation of the this header file: https://github.com/Azure/iotedge/blob/master/edgelet/hsm-sys/azure-iot-hsm-c/inc/hsm_client_data.h I've kept a lot of the C implementation code from the linked repository but have modified the implementation of some of the headers to use C++ instead.

Please let me know if any additional details are required.

I've tried switching back to older versions of g++ (4.9) to build the C and C++ shared library but it always yields an artifact that has an ABI of GNU/Linux.

This question was identified as a duplicate of this one Can I call C or C++ functions from Rust code? but the answers to those questions haven't helped solve my problem as the suggestions/answers on that post state that C++ can be called by passing through a C 'interface' which is exactly what I have. The problem is more of an ABI incompatibility issue for a specific target architecture i.e., aarch64. The problem doesn't reproduce on an amd64 target architecture.

Expected - The Rust executable and the dynamic shared library built using both C and C++ to have compatible ABIs for aarch64.

Actual - Rust executable is targeting the SYSV ABI whereas the dynamic shared library is targeting the GNU/Linux ABI.

kodr
  • 51
  • 1
  • 4
  • 4
    I don't think there's anything guaranteeing rust/c++ binary compatibility.. at least not anything I've heard of. – Jesper Juhl Jul 23 '19 at 19:24
  • 6
    There's nothing that guarantees C++ ABI compatibility, period. – Shepmaster Jul 23 '19 at 19:25
  • @Eljay this is the API surface of the shared library - https://github.com/Azure/iotedge/blob/master/edgelet/hsm-sys/azure-iot-hsm-c/inc/hsm_client_data.h The source in the linked repository is all C but I have an implementation of this API surface which is a combination of C and C++ instead. The source in the linked repository when compiled with the same linaro toolchain yields a library with the SYSV ABI (which I'm guessing is due to gcc use only) whereas compiling the implementation I have (with both C/C++) yields a binary with the GNU/Linux ABI instead – kodr Jul 23 '19 at 19:47
  • @JesperJuhl are you aware of any guidance on how to link dynamic libraries to Rust executables? The repository I've linked in my comment above has the Rust executable I had mentioned in my question (https://github.com/Azure/iotedge/tree/master/edgelet/iotedged) which links successfully against a C implementation of the shared library present here: https://github.com/Azure/iotedge/tree/master/edgelet/hsm-sys/azure-iot-hsm-c – kodr Jul 23 '19 at 19:50
  • Thank you. I did not know there were differences in the C ABI for GNU/Linux and SYSV. I learned something new. +1 – Eljay Jul 23 '19 at 19:51
  • @Shepmaster tagging you here to get your thoughts on the same question I've asked in my response to JesperJuhl above. – kodr Jul 23 '19 at 19:51
  • Possible duplicate of [Can I call C or C++ functions from Rust code?](https://stackoverflow.com/questions/24105186/can-i-call-c-or-c-functions-from-rust-code) – Stargateur Jul 23 '19 at 20:09
  • "are you aware of any guidance on how to link dynamic libraries to Rust executables" - No. Sorry. – Jesper Juhl Jul 23 '19 at 20:10
  • @Stargateur I believe I went through that post earlier. As you mention in your answer to the question on that post - "So, to call C++ from Rust, you must pass by C.", that is exactly what's happening my my case too. The problem here is more of an ABI incompat issue on aarch64 target architectures. As stated earlier, the dynamic loading of the shared library works perfectly on amd64 machines. – kodr Jul 23 '19 at 20:13
  • In your question you are mixing C and C++, "C/C++" that very unclear when you want to talk of C or when you want to talk of C++. Please [edit] your question to avoid mixing two languages specially when you talk about ABI that are both implementation behavior and totally different between C and C++. – Stargateur Jul 23 '19 at 20:17
  • @Stargateur Just edited the question to add a bit more clarification. The reason I mentioned C/C++ both is because the library has code in both languages. To provide a brief overview, the library is an implementation of the this header file: https://github.com/Azure/iotedge/blob/master/edgelet/hsm-sys/azure-iot-hsm-c/inc/hsm_client_data.h I've kept a lot of the C implementation code from the linked repository but have modified the implementation of some of the headers to use C++ instead. I'll add this information to the question too – kodr Jul 23 '19 at 20:22

0 Answers0