Misc. bug: Hexagon session fails when /vendor/lib64 is on LD_LIBRARY_PATH (Termux, SM8850)

Open Beginner friendly
#27,677 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
1/5
Estimated time
Under an hour
Newbie friendliness
88/100
Issue type
Documentation
Clarity
Clearly specified
Activity status
Active
Tech stack
android, cpp, shell

Research direction

Start with docs/backend/snapdragon/README.md and compare its documented library-path setup with scripts/snapdragon/adb/run-cli.sh:69-72 and the Termux reproduction in the issue. Document the warning about keeping /vendor/lib64 off LD_LIBRARY_PATH when using non-adb execution, and verify that the guidance matches the existing adb scripts.

Written by the indexing model from the issue text.

Description

Name and Version
version: 0.2.0-dev (build 1, commit f280b26)
built with Clang 21.0.0 for Android aarch64

Built in ghcr.io/snapdragon-toolchain/arm64-android:v0.7, preset arm64-android-snapdragon-release, cmake 3.31.6.

Operating systems

Other? (Please let us know in description)

Which llama.cpp modules do you know to be affected?

libllama (core library), llama-bench, llama-cli

Command line
GGML_HEX_VERBOSE=1 LD_LIBRARY_PATH=$PWD/lib:/vendor/lib64 ADSP_LIBRARY_PATH=$PWD/lib \
  ./bin/llama-bench -m gguf/Llama-3.2-1B-Instruct-Q4_0.gguf -dev HTP0 -ngl 99 -p 32 -n 8
Problem description & steps to reproduce

I run llama.cpp from Termux instead of the adb scripts. If /vendor/lib64 is on LD_LIBRARY_PATH, the Hexagon backend can't open a session. Take it off and it works. Nothing else changes between the two runs.

/vendor/lib64 is on there because of OpenCL. libggml-opencl.so has a hard NEEDED on libOpenCL.so, that lives in /vendor/lib64, and Termux's linker won't load it from an absolute path unless the directory is on LD_LIBRARY_PATH. So I can have OpenCL or I can have Hexagon, not both.

Device is a OnePlus 15 (CPH2747), Snapdragon 8 Elite Gen 5 (SM8850), Hexagon v81, Android 16 (SDK 36), OxygenOS CPH2747_16.0.9.400(EX01). No root.

With /vendor/lib64:

ggml_opencl: device: 'QUALCOMM Adreno(TM) 840 (OpenCL 3.0 Adreno(TM) 840)'
ggml-hex: Loading driver libcdsprpc.so
ggml-hex: FastRPC capability query failed (err 114)
ggml-hex: failed to query HTP version (err 114) defaulting to v73
ggml-hex: Hexagon Arch version v73
ggml-hex: HTP0 allocating new session
ggml-hex: failed to open session 0 : error 0x72
ggml-hex: failed to create device/session 0
ggml/src/ggml-backend.cpp:569: GGML_ASSERT(device) failed
2: ggml_abort
3: ggml_backend_dev_description
4: ggml_backend_dev_by_name
7: _Z11llama_benchiPPc

Exit 134. Same command without that one path element:

ggml_opencl: platform IDs not available.
ggml-hex: Hexagon Arch version v81
ggml-hex: HTP0 hwinfo: threads 8, hvx 8, hmx 1, vtcm 8 MB
ggml-hex: HTP0 new session : session-id 0 domain-id 3 uri file:///libggml-htp-v81.so?htp_iface_skel_handle_invoke&_modver=1.0&_dom=cdsp&_session=0
| llama 1B Q4_0 | 729.75 MiB | 1.24 B | OpenCL,HTP | 99 | HTP0 | pp32 | 698.21 ± 95.79 |
Why the path does that

/dev/fastrpc-cdsp here is crw-rw-r-- system system, so an app uid can't open it. libcdsprpc.so expects that and asks the vendor.qti.hardware.dsp.IDspService HAL for an fd instead. Turning on its tracing (setprop vendor.fastrpc.debug.trace 1) shows the fallback dying:

fastrpc_apps_user.c:5866: open_device_node: no access to default device of domain 3, open thru HAL, (sess_id 0)
dsp-client: DspClient.cpp (61): DspClient: AIDL HAL not found, using HIDL interface
dsp-client: DspClient.cpp (101): Error: DspClient: unable to acquire dspservice instance
dsp-client: DspClient.cpp (161): Error: openSession: IDspManager session is NULL
dsp-client: DspClient.cpp (226): Error: open_hal_session: failed to open session, error -1

"AIDL HAL not found" isn't true. /vendor/bin/dspservice is up and service list has vendor.qti.hardware.dsp.IDspService/default. The lookup itself is what the library path breaks. Same process, same uid, one variable:

isDeclared: True   getService: 0xb400...      (no LD_LIBRARY_PATH)
isDeclared: False  getService: 0x0            (LD_LIBRARY_PATH=/vendor/lib64)
How far this goes

Probably not very. #23821 has someone running LD_LIBRARY_PATH=./lib:/vendor/lib64 ... -dev HTP0 on Android quite happily. My guess is it only hurts devices where the app uid can't open the fastrpc node, so libcdsprpc has to use the HAL in the first place. If your fastrpc permissions are looser the fallback never runs and the extra path element does nothing.

The adb scripts are fine. scripts/snapdragon/adb/run-cli.sh:69-72 sets only the package lib, same as its siblings:

adb $adbserial $adbhost shell " \
  cd $basedir; ulimit -c unlimited;        \
    LD_LIBRARY_PATH=$basedir/$branch/lib   \
    ADSP_LIBRARY_PATH=$basedir/$branch/lib \

I pushed the same build to /data/local/tmp and ran it that way as uid 2000 to check. Both backends came up, OpenCL included, with no /vendor/lib64 anywhere:

ggml_opencl: device: 'QUALCOMM Adreno(TM) 840 (OpenCL 3.0 Adreno(TM) 840)'
ggml-hex: Hexagon Arch version v81
ggml-hex: HTP0 new session : session-id 0 domain-id 3 ... _dom=nsp1000&_session=0
| llama 1B Q4_0 | OpenCL,HTP | 99 | HTP0 | pp32 | 657.70 ± 117.13 |

So your documented path is fine. This is a Termux problem.

What would have helped

One line in docs/backend/snapdragon/README.md: if you're not using the adb scripts, keep /vendor/lib64 off LD_LIBRARY_PATH, it can break FastRPC's HAL fallback. Cost me a day.

What I do instead is copy libcdsprpc.so, vendor.qti.hardware.dsp@1.0.so, vendor.qti.hardware.dsp-V1-ndk.so, libvmmem.so and libOpenCL.so into the package's own lib/. Both backends survive that.

The abort is a different problem and already has a fix open at #20983. I've left this reproduction there too.

Two things I checked so I don't waste your time: the arch-query failure isn't the fatal bit, ggml-hexagon.cpp:4404 logs and carries on at v73 on purpose. And I'm not going to guess at an AEE name for 0x72 since AEEStdErr.h isn't in the tree, though 114 == 0x72 so those two lines are probably the same status printed with %d and %x.

First Bad Commit

Didn't bisect, only tested f280b26.


Disclosure: I used an AI assistant to help collect the logs and track this down to the linker path. Every command and result above ran on my device and I checked them.

Dominant language
C++
Stars
129k
Forks
23.5k
Avg merge
2d 11h
Merged PRs (30d)
411

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from ggml-org/llama.cpp

All issues in ggml-org/llama.cpp

Similar issues

More C++ issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.