首页 时政热点 科技头条 智能AI 安全攻防 数码硬件 开发者生态 汽车 游戏 社会热点 开源推荐 医疗健康 归档 标签 关于

Solo – 静态 Linux 二进制文件的 .so 加载器

2026-08-19 1 阅读 约9分钟阅读 zX41ZdbW
分享:
字号:
SoLo — 静态 Linux 二进制文件的 .so 加载程序 发布一个 musl 链接的可执行文件。在运行时,加载用户现有的 glibc 链接的 GPU 驱动程序。进程中没有容器,没有 AppImage,也没有第二个 libc。静态二进制文件是在 Linux 上部署软件的一种非常无聊的方式:一个文件,没有依赖项,没有什么可以破坏的。我们使用 IX 构建我们的系统,这是一个源优先的构建系统,用于生成完全静态的 Linux 二进制文件。当应用程序需要 GPU 时,无聊就结束了:Vulkan 和 OpenGL 驱动程序由主机作为共享对象提供,通常针对 glibc 构建,并且完全静态的 musl 二进制文件通常无法 dlopen() 它们。 SoLo 跨越了这个界限。它提供了一个 dlfcn 风格的源 API,由自己的 ELF 加载器(x86-64 和 aarch64)支持,以及一个在 musl 之上实现的 glibc ABI 桥。结果仍然是一个普通的静态可执行文件,但它可以使用计算机上已安装的图形驱动程序。该存储库包括端到端 Vulkan 证明:完全静态的可执行文件加载主机未经修改的 Vulkan 驱动程序,运行计算着色器,并将结果写入 PNG。在 Linux 下的 AMD radv、radeonsi、Intel 和 NVIDIA GPU 上以及 Asahi Linux 下的 Apple M1 上进行了测试。主机保留硬件特定的代码。你运送其他所有东西。不仅仅是演示中的话:每次提交时,CI 都会通过 SoLo 在 x86-64 和 aarch64 上加载 1,000 个安装最多的 Debian 软件包(超过 2,100 个主机对象)的共享库。获取预构建的二进制文件 - 无需克隆,无需工具链,任何安装了 Vulkan 驱动程序的 Linux(mesa-vulkan-drivers 就足够了):curl -LO https://github.com/pg83/solo/releases/latest/download/vulkan-x86_64 chmod +x vulkan-x86_64 ./vulkan-x86_64 hello.png vulkan-aarch64 与 arm64 的演示相同机器。该命令以通常的方式发现发行版安装的 Vulkan ICD 并生成 512×512 RGBA 图像。这就是我们构建 Shitty 版本二进制文件的方式——顺便说一句,一个速度极快的终端模拟器!要强制使用特定驱动程序: ./vulkan-x86_64 --driver /usr/share/vulkan/icd.d/radeon_icd.x86_64.json radeon.png ./vulkan-x86_64 --driver /usr/share/vulkan/icd.d/lvp_icd.json lavapipe.png ICD 清单名称在不同发行版之间略有不同。不传递 --driver 让嵌入式 Khronos 加载器执行其正常发现。您可以验证可执行文件本身不是动态链接的:readelf -lW ./vulkan-x86_64 | grep INTERP # no output readelf -dW ./vulkan-x86_64 # "There is nodynamicsection" 或者从源代码构建相同的演示,在 PATH 中使用 Python 3 和 C/C++ 编译器: git clone https://github.com/pg83/solo.git cd alone ./build vulkan ./vulkan hello.png 这不是对 vkCreateInstance 的玩具调用。演示:进入静态链接的 Khronos Vulkan 加载器;通过 SoLo 加载主机的 Vulkan ICD 及其非 glibc 依赖项;创建设备、存储缓冲区、描述符集和计算管道;调度签入的 SPIR-V 着色器;映射结果并通过静态链接的 libpng 写入。完整的示例位于 bin/vulkan 中,Vulkan 程序本身位于 main.cpp 中。 ┌────────────────── 全静态可执行文件 ──────────────────┐ │ │ │ 应用 → 嵌入式 Vulkan 加载器 → SoLo dlopen/dlsym │ │ ├─ x86-64 ELF 映射器 │ │ └─ glibc ABI → musl │ │ │ │ └────────────────────────────────────────┬────────────────────┘ │ 在运行时映射 ▼ 系统 Mesa/Vulkan ICD.so + DSO elf_loader.cpp 映射 ELF 段,行走 DT_NEEDED ,解析版本符号,应用 x86-64 重定位,支持 ELF TLS 和 TLSDESC,实现IFUNC、应用 RELRO 并运行初始化程序。本身就是 ELF DSO 的依赖项会被递归加载。 glibc 是故意不加载的。诸如 malloc@GLIBC_2.2.5 之类的导入由 glibc_shim.cpp 在进程的现有 musl 运行时解析为 ABI 正确的适配器。不受支持的 glibc 函数具有独特的生成存根,如果调用它们,这些存根会以确切的符号和版本大声失败,而不是默默地破坏进程。由于 musl 将其同步对象的大小调整为每个体系结构的 glibc ABI,因此桥不会隐藏它们:驱动程序创建的 pthread_mutex_t 就位使用。因此,锁对于加载的 DSO 和可能共享它的静态可执行文件都是一个锁,并且 glibc 的静态递归和错误检查初始化程序在第一次使用时采用。在从磁盘加载 DSO 之前,SoLo 检查其静态提供程序注册表。这使得应用程序可以通过已链接到可执行文件的函数来满足依赖关系(例如 Wayland)。 LD_LIBRARY_PATH 和 DL_ELF_LIBRARY_PATH 适用于标准系统目录之外的库。有趣的部分足够小,足以阅读:默认目标构建独立存档:发布的 ./dlfcn 符号链接指向生成的 libdlfcn.a 。包含 lib/dlfcn.h ,将存档链接到 musl-static 应用程序,普通 dlopen() / dlsym() 调用将重定向到 SoLo。源代码树是故意独立的并且
这篇文章对您有帮助吗?

订阅66必读

每日精选科技资讯,直达你的邮箱