chrpath用于修改ELF文件的rpath或runpath,需用-r指定新路径,现代系统推荐-c强制写入DT_RUNPATH;若文件被strip则失效,可用patchelf替代。

chrpath 修改 ELF 文件 rpath 的基本用法
直接改 rpath 不需要重编译,chrpath 就是干这事的。它修改的是 ELF 文件中 `.dynamic` 段里的 DT_RPATH 或 DT_RUNPATH 条目,生效前提是程序没被 strip 掉动态段信息(否则会报错 Not an ELF file 或 No rpath or runpath tag found)。
最常用命令格式:
chrpath -r <new-path> <binary>
例如把 /usr/local/lib 设为运行时库搜索路径:
chrpath -r '/usr/local/lib' ./myapp
-
chrpath默认只处理DT_RPATH;如果目标文件用的是DT_RUNPATH(现代链接器默认),需加-c选项强制创建或替换(见下一条) - 路径里不能有空格或 shell 特殊字符,否则要加单引号包裹
- 修改后可用
readelf -d ./myapp | grep -E 'rpath|runpath'验证是否写入成功
chrpath -c 强制写入 runpath(现代系统推荐)
从 ld 2.30+ 开始,默认生成 DT_RUNPATH 而非 DT_RPATH,因为前者优先级更低、更安全(受 LD_LIBRARY_PATH 影响,且不被 setuid 程序忽略)。但 chrpath 默认不碰 DT_RUNPATH —— 这是很多人改了却没生效的根本原因。
必须显式用 -c 才能创建/覆盖 DT_RUNPATH:
chrpath -c -r '/opt/mylib:/usr/lib/mydep' ./myapp
-
-c表示 “create or replace”,不管原来有没有rpath/runpath都强行写入DT_RUNPATH - 多个路径用冒号
:分隔,和LD_LIBRARY_PATH规则一致 - 如果二进制原本只有
DT_RPATH,-c会删掉它、新建DT_RUNPATH;反之亦然
常见失败场景与绕过方法
遇到 Operation not permitted 或 File has no section headers 别急着换工具,先看是不是这几个硬伤:
- 文件被
strip过:strip 会删掉 `.dynamic` 段,chrpath完全无从下手;用file ./myapp看是否含not stripped,不含就只能重编译或换patchelf - 文件是 PIE 可执行文件且只读:某些发行版(如 Fedora)默认设
noexec或relro,临时去掉写保护:chmod +w ./myapp再试 - 路径超长:ELF 规范限制
rpath字符串最大约 1024 字节,超过会截断;用chrpath -l ./myapp查当前长度,精简路径或用环境变量替代 - 权限不足:普通用户无法修改系统目录下的二进制(如
/bin/ls),这不是chrpath的问题,是 Linux 权限模型本身限制
chrpath 和 patchelf 的关键区别
别把 chrpath 当万能补丁——它只是个轻量编辑器,能力边界很清晰:
-
chrpath只能修改已有rpath/runpath字段,不能增删动态段、不能改DT_NEEDED、不能处理静态链接部分 -
patchelf更底层,能新增段、重写 interpreter、甚至伪造DT_RUNPATH到没有该字段的文件里(适合 strip 后的文件) - 如果只需要改路径且文件未 strip,
chrpath更快、无依赖、不易出错;其他情况直接上patchelf --set-rpath
真正容易被忽略的是:rpath 生效依赖于 loader 行为,而不同 glibc 版本对 DT_RPATH 和 DT_RUNPATH 的解析逻辑有细微差异,线上部署前务必在目标环境用 ldd ./myapp 实测是否真能 resolve 到你指定的库。


















