Under what circumstances will non-PIC internals in a shared library work?

2026-05-14

Stack Overflow: View Question

Tags: linker

Score: -1 | Views: 59

The asker is wrapping FFmpeg (and its static dependencies) into a single shared library exposing a C++ API for Deno's FFI. They want the FFmpeg internals statically linked into the .so, but some of those object files weren't compiled with -fPIC. They're asking when this can be made to "just work."

Why it's interesting: the question sits at the seam between three pieces of ELF/PE machinery that most developers happily ignore — position-independent code, text relocations, and the loader's address-space layout. The naïve answer ("you must use -fPIC") is wrong; the precise answer ("it depends on the architecture, relocation types, and whether the loader permits DT_TEXTREL") is what makes this worth writing up.

Sketch of an answer:

Practical guidance for the asker: if FFmpeg's build emits non-PIC .a files on x86-64 Linux, the resulting .so will probably load and run. Verify with readelf -d libfoo.so | grep TEXTREL — if that flag is absent, you're fine; if present, you've silently signed up for writable text pages and incompatibility with anything that disallows them (notably noexec mounts and some sandboxes Deno may eventually run inside).

Gotchas: LTO can hide the problem until link time. Cross-compiled distributions (Alpine/musl, NixOS hardened) sometimes refuse DT_TEXTREL at runtime even when GNU ld emitted it. And if Deno ever moves its FFI workers into a seccomp-restricted sandbox, an mprotect(PROT_WRITE) on text from the loader will be the failure mode.

The challenge: "Does non-PIC work in a shared library?" is really a question about which relocation types your target architecture emits and whether the dynamic loader will tolerate DT_TEXTREL — and the honest answer is "on amd64, usually yes; everywhere else, plan for pain."

All newsletters