0

I am trying to call a function from closed-source library. Original toolchain is not available, library headers not available.

$ file libvendor.so 
libvendor.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=ff, stripped

$ nm -CD libvendor.so | grep Start
0001ec3a T nm::vendor::className::Start(int, char const**, std::__1::function<void ()>)

Recreated header file:

#include <functional>

namespace nm {
    namespace vendor {
        class className {
        public:
            static className* Get();
            void Start(int, char const**, std::function<void ()>);
        }
    }
}

main.cpp:

#include "header.h"

using namespace nm::vendor;
using namespace std;

std::function<void ()> startFunc;
void Start() {}

int main(void)
{
    className* c = className::Get();
    char const *str = "c style string";
    const char** str_ptr = &str;
    startFunc = Start;
    c->Start(1, str_ptr, startFunc);
}

Compiling, I am using crosstool-ng:

$ ~/x-tools/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-c++  --version
arm-linux-gnueabihf-c++ (crosstool-NG 1.25.0) 11.2.0

$ ~/x-tools/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-c++ \
    -std=c++11 \
    -Wl,-v \
    -Wl,-rpath,. \
    -ldl \
    -mthumb-interwork \
    libvendor.so \
    -o main \
    main.cpp
collect2 version 11.2.0
~/x-tools/arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/11.2.0/../../../../arm-linux-gnueabihf/bin/ld -plugin ~/x-tools/arm-linux-gnueabihf/libexec/gcc/arm-linux-gnueabihf/11.2.0/liblto_plugin.so -plugin-opt=~/x-tools/arm-linux-gnueabihf/libexec/gcc/arm-linux-gnueabihf/11.2.0/lto-wrapper -plugin-opt=-fresolution=/tmp/cc35fC2k.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --sysroot=~/x-tools/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot --eh-frame-hdr -dynamic-linker /lib/ld-linux-armhf.so.3 -X -m armelf_linux_eabi -o main ~/x-tools/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/lib/crt1.o ~/x-tools/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/lib/crti.o ~/x-tools/arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/11.2.0/crtbegin.o -L~/x-tools/arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/11.2.0 -L~/x-tools/arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/11.2.0/../../../../arm-linux-gnueabihf/lib -L~/x-tools/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot/lib -L~/x-tools/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/lib -v -rpath . -rpath /system/vendor/sony/lib -rpath ~/nw-a50/myfirmware/bootimg/initrd_unpacked/lib/ -ldl libvendor.so /tmp/ccKaDp0K.o -lstdc++ -lm -lc -lgcc_s -lgcc -lc -lgcc_s -lgcc ~/x-tools/arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/11.2.0/crtend.o ~/x-tools/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/lib/crtn.o
GNU ld (crosstool-NG 1.25.0) 2.26.1
/tmp/ccSbQv2E.o: In function `main':
main.cpp:(.text+0x70): undefined reference to `nm::vendor::className::Start(int, char const**, std::function<void ()>)'
collect2: error: ld returned 1 exit status

__1 is a inline namespace; compilation fails if specified in header function declaration:

In file included from main.cpp:2:0:
header.h:84:57: error: 'std::__1' has not been declared
             void Start(int, char const**, std::__1::function<void ()>);

Other functions (such as Get()) are correctly resolved by linker and callable.

Is there a way to satisfy linker?

Answer: downgrade llvm to 7.

user1938027
  • 135
  • 7
  • 1
    I would close the question as a dupe of https://stackoverflow.com/questions/29293394/where-does-the-1-symbol-come-from-when-using-llvms-libc – 273K May 29 '23 at 01:44
  • It's LLVM C++11 standard library, thus you should use LLVM clang with -std=c++11 and -stdlib=libc++. – 273K May 29 '23 at 01:45
  • BTW mangled names do not encode returned values. – 273K May 29 '23 at 01:46
  • `main.cpp:(.text+0x9c): undefined reference to 'nm::vendor::className::Start(int, char const**, std::function)'`, invocation: https://pastebin.com/raw/gUbNfktA – user1938027 May 29 '23 at 02:36
  • 1
    They don't seem to have inline namespaces `__1` anymore. You can try to downgrade llvm. – 273K May 29 '23 at 03:20
  • downgrading llvm to 7 worked, thanks for your help – user1938027 May 29 '23 at 19:31

0 Answers0