Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dlopen failed: cannot locate symbol "lua_pushboolean" - aarch64-linux-android target #471

Closed
scottmckendry opened this issue Oct 20, 2024 · 10 comments

Comments

@scottmckendry
Copy link

Getting this error when trying to load this library on Android (Termux). This doesn't appear to be a problem on any other targets. Builds for macos, windows & linux all work as expected.

Is there a flag or dependency that is required to get this working?

Building using cross on the ubuntu-latest Github action runner.

Cargo.toml
.cargo/config.toml

Let me know if any other info is required 🙂

@khvzak
Copy link
Member

khvzak commented Oct 25, 2024

Could you tell how you load the module and can you load any other Lua C libraries?

@scottmckendry
Copy link
Author

It's loading through Neovim using LuaJIT, I believe. Output of nvim --version shows LuaJIT 2.1.

Not sure about loading other libs. I've not worked with C, so my knowledge is quite lacking in this area. Is there a common lib I can test with that will give us some more information?

@scottmckendry
Copy link
Author

Not sure if this is relevant at all, but loading libm appears to work fine on Android. The following Lua code works as expected:

local ffi = require("ffi")

ffi.cdef([[
    double sin(double x);
]])

local mathlib = ffi.load("m")
local angle = 1
print("sin(", angle, ") = ", mathlib.sin(angle))

@s-cerevisiae
Copy link

Tested with blink.cmp and a minimal module I just wrote, this seems to only happen when the module is required in Neovim. Using it in luajit is fine as far as I can tell. So there must be something different in Neovim on Termux.

@khvzak
Copy link
Member

khvzak commented Nov 19, 2024

Loading libraries through ffi is not the same as loading Lua modules.

Could you try to load Lua cjson module? Likely the root cause is that neovim was built without exporting Lua symbols.

pipcet pushed a commit to pipcet/mlua that referenced this issue Nov 19, 2024
@pipcet
Copy link

pipcet commented Nov 19, 2024

My understanding is this is due to a peculiarity of the Android linker/loader (/system/bin/linker64). IIRC, for whatever reason, Android does not export symbols exported by the executable or its dependencies to dlopen()ed libraries.

mlua currently generates libraries without a DT_NEEDED entry. Adding an entry for libluajit.so fixes things on Android, at least in one test case.

pipcet@0a590d0 is a potential fix, and allows dlopen("/path/to/lua/library.so") to succeed, at least on my phone.

I assume there are good reasons to avoid the DT_NEEDED entry on Linux systems, but I don't understand them, so it's possible they also apply to Android and we need a different workaround.

@khvzak
Copy link
Member

khvzak commented Nov 19, 2024

mlua currently generates libraries without a DT_NEEDED entry.

This is right. The same native Lua module targeted to (for example) 5.1 should be loadable by Lua 5.1.0, ..., 5.1.5, JIT.
But If you link module with LuaJIT then loading it in Lua 5.1 will guarantee to segfault (and vice versa).
Moreover, host application can be statically linked with Lua interpreter (without having any shared libraries) but still should be able to load Lua modules.

@khvzak
Copy link
Member

khvzak commented Nov 19, 2024

If you want to link module with LuaJIT, you can pass linker args:

.cargo/config.toml

[target.aarch64-linux-android]
rustflags = ["-C", "link-args=-lluajit"]

OR compile with:

RUSTFLAGS="-C link-args=-L/path/to/lib -C link-args=-lluajit" cargo build

@pipcet
Copy link

pipcet commented Nov 20, 2024

mlua currently generates libraries without a DT_NEEDED entry.

This is right. The same native Lua module targeted to (for example) 5.1 should be loadable by Lua 5.1.0, ..., 5.1.5, JIT. But If you link module with LuaJIT then loading it in Lua 5.1 will guarantee to segfault (and vice versa). Moreover, host application can be statically linked with Lua interpreter (without having any shared libraries) but still should be able to load Lua modules.

Thanks for explaining! Shipping libraries without a DT_NEEDED entry won't work on Android (except, accidentally, for binaries that use dlopen to open libluajit.so) due to linker breakage, I'm afraid, so this "feature" won't work on that system.

@scottmckendry
Copy link
Author

This is fixed now. More details on the issue here:

termux/termux-packages#22343

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants