autopatchelf - what it can look like

Published 2020-12-02 on Farid Zakaria's Blog

This is a follow up post to my previous one to on-demand linked libraries for NixOS.

I previously wrote about the work into a new NixOS tool nix-ld, which will allow the possibility of hot-patching the linking of dynamic libraries.

At the moment the goal of the tool is modest in allowing modification of the library search path via a custom environment variable NIX_LD_LIBRARY_PATH.

I’m minimizing the task as there’s a ton of complexity, such as not loading in a different glibc and other subtleties – ask Mic92 about it on #nixos!

I finished with a bit of a teaser on what a full-fledged tool may look like…

autopatchelf

autopatchelf is my work in progress in what the other half of on-demand linked libraries may look & feel like.

Don’t judge me on the code, it’s still in exploratory phase. 👨‍⚖️

It’s goal is quite simple and works in tandem with nix-ld. autopatchelf attempts to locate a valid /nix/store entry for every required library required by the binary.

An asciinema is worth a thousand words.

Here is a small example of how running autopatchelf will prompt the user to select the most appropriate matching library for the Ruby binary. It’s pretty quick..

Once the libraries are chosen, it’s mostly a straightforward invocation to nix-ld with the set NIX_LD_LIBRARY_PATH environment variable.

Challenges

I already foresee a few challenges (all solvable!) that need to be addressed for a thorough solution which I want to articulate here for others that might want to pursue this idea.

  1. A garbage-collection root must be created for all realised /nix/store entries. This is to avoid the chosen libraries from being garbage-collected during process run.

  2. autopatchelf will try to normalize or find closest matching libraries if a non-exact match can be found. The ELF binary itself then must be patched to set the selected names.

  3. Solving for diamond dependencies must be performed. For instance, the selected glibc version must match the same one used in all the selected /nix/store paths. It may be necessary to build a depth-first graph of selected libraries.

  4. A cache file “fingerprint” of the selected libraries can be saved for the binary so that subsequent startups are faster.

  5. An option to directly edit the ELF binary rather than supply the NIX_LD_LIBRARY_PATH variable should be possible.

The long-term vision is anyone can either start any non-NixOS binary if this functionality is directly embedded within the ld interpreter, patch the ELF binary interactively for the required libraries or even ship the “fingerprint” file alongside the binary for others to consume.

There’s a lot of promise in the idea especially for unlocking cases where users may lean on buildFHSUserEnv.

If you’d like to work on this together reach out to me or contribute at https://github.com/fzakaria/autopatchelf