box64 icon indicating copy to clipboard operation
box64 copied to clipboard

VCV Rack: __cxa_pure_virtual symbol not found and dlopen() discrepancies

Open Simon-L opened this issue 3 years ago • 6 comments

Trying to run VCV Rack on Pine64. Self compiled from git. I've extracted libjack.so.0 and libdb-5.3.so from the amd64 deb packages and put them in the working directory.

The following error message is repeated many times with different addresses when the program starts:

Error: Symbol __cxa_pure_virtual not found, cannot apply R_X86_64_64 @0xffff989aee88 ((nil)) in libRack.so

It then crashes when the audio processing is supposed to start with an unimplemented opcode error: 6654|0xffffb431f1b0: Unimplemented Opcode (00) 66 0F 38 3F C1 66 41 0F 7E C6 4D 89 F7 85 D2 Paste with LOG=2 including some context, error appears at line 116.

Cool thing is VCV Rack is open-source! In fact some work has been done to compile it and many of its plugins for arm64, although closed source modules aren't available for arm64, hence my attempt.

Thanks for any help!

Simon-L avatar May 03 '22 00:05 Simon-L

Thank you very much for the quick fix!

The __cxa_pure_virtual error is also fixed when building my own version of VCV Rack directly from their git repository, not sure what fixes it exactly.

It looks bad but I don't worry too much about that, the headless version runs fine... until I tried to add another plugin.

Plugins are scanned and loaded on program startup, it seems to work fine for the first module but crashes if another one is found. Plugin files are all named plugin.so, could it be that the wrapping loader in box64 gets confused because of that?

[36.411 info adapters/standalone.cpp:175 main] Initializing plugins
[36.413 info src/plugin.cpp:119 loadPlugin] Loading Core plugin
[36.436 info src/plugin.cpp:179 loadPlugin] Loaded Core v2.1.0
[36.450 info src/plugin.cpp:121 loadPlugin] Loading plugin from /home/user/.Rack2/plugins/MockbaModular
Using emulated /home/user/.Rack2/plugins/MockbaModular/plugin.so
[36.809 info src/plugin.cpp:179 loadPlugin] Loaded MockbaModular v2.0.0
[36.810 info src/plugin.cpp:121 loadPlugin] Loading plugin from /home/user/.Rack2/plugins/Fundamental
box64: src/plugin/Plugin.cpp:23: void rack::plugin::Plugin::addModel(rack::plugin::Model*): Assertion `!model->plugin' failed.
[1]    7757 abort (core dumped)  box64 Rack -h -d -s . -u ~/.Rack2 ~/box64test.vcv

That assert basically ensures that the plugin wasn't already loaded, hence my suspicion.

Something I've been thinking: is it possible to use box64 as a wrapper for the plugins and keep the main program native? I'm sure Rack could be built for arm64, the performance would also be much better! Thanks.

Simon-L avatar May 04 '22 10:05 Simon-L

Yes, box64 as a lib (in the way you mean) would be a nice thing... but I don't think ptitseb has a plan to do so.

neofeo avatar Jun 04 '22 21:06 neofeo

I updated the title to reflect the progress on this.

It turns out my intuition was right about dlopen() and multiple files with the same name. I modified the plugins and loading code in VCV Rack to use different names and the assert error is fixed.

I attach a bare minimum C++ example, here is a simplified gist. box64sonames.zip

Output on x64:

./sonames
Loading function from shared1...Hello from obj1!
Loading function from shared2...Hello from obj2!

Output on box64:

% box64 sonames
Dynarec for ARM64, with extension: ASIMD AES CRC32 PMULL PageSize:4096
Box64 with Dynarec v0.1.9 1057b88 built on Jun  8 2022 02:27:46
Using default BOX64_LD_LIBRARY_PATH: ./:lib/:lib64/:x86_64/:bin64/:libs64/
Using default BOX64_PATH: ./:bin/
Counted 34 Env var
Looking for sonames
Using native(wrapped) libdl.so.2
Using native(wrapped) libc.so.6
Using native(wrapped) ld-linux-x86-64.so.2
Using native(wrapped) libpthread.so.0
Using native(wrapped) librt.so.1
Loading function from shared1...Using emulated shared1/sharedobj.so
Hello from obj1!
Loading function from shared2...Hello from obj1!

It actually only loads one of the so, so the call is to the same function.

Simon-L avatar Jun 09 '22 16:06 Simon-L

Regarding __cxa_pure_virtual symbol not found, I also made a bare minimum example: https://gist.github.com/Simon-L/319200437ebb5402bb43f76e39169a9a Which triggers a similar error:
Error: PltResolver: Symbol __cxa_pure_virtual(ver 1: __cxa_pure_virtual) not found, cannot apply R_X86_64_JUMP_SLOT 0xffffa5234018 (0xffffa5231036) in /home/user/purevirtual

Fwiw, this symbol is more precisely an error handler for calls to pure virtual functions. Most of the time libstdc++ provides it and you get pure virtual method called.
Statically linking is a little different and this is where it gets beyond my personal understanding :) SO answer with some details: https://stackoverflow.com/a/14082540

Thank you for your amazing work!

Simon-L avatar Jun 09 '22 16:06 Simon-L

Ok, so I added a dummy __cxa_pure_virtual function that just print "Pure virtual function called" and abort. And I also added support for multiple different libs with same name... Your sample works in box64 now (should also works on box86)

ptitSeb avatar Jun 11 '22 11:06 ptitSeb

Can you test, to check if this ticket can be closed or not?

ptitSeb avatar Jul 03 '22 12:07 ptitSeb

No news from op, closing the ticket.

ptitSeb avatar Jan 24 '23 08:01 ptitSeb