Haskell用LLVM构建静态库加-fPIC仍报无法创建动态重定位错误
GHC生成静态库LLVM bitcode时的重定位报错解决方案
问题复现配置
尝试通过GHC为静态库生成LLVM bitcode时,使用如下编译配置:
FILE = lib compile: ghc -fllvm -keep-llvm-files -fforce-recomp -static -shared -flink-rts -fPIC $(FILE).hs llvm-as $(FILE).ll -o $(FILE).bc
测试用Haskell代码lib.hs内容:
-- lib.hs module Lib where add x y = x + y
执行编译命令后触发报错:
$ ghc -fllvm -keep-llvm-files -fforce-recomp -static -shared -flink-rts -fPIC lib.hs [1 of 1] Compiling Lib ( lib.hs, lib.o ) You are using an unsupported version of LLVM! Currently only 9 to 13 is supported. System LLVM version: 13.0.0 We will try though... Linking a.out ... ld.lld: error: cant create dynamic relocation R_X86_64_32S against symbol: stg_bh_upd_frame_info in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output >>> defined in /home/user/.ghcup/ghc/9.2.1/lib/ghc-9.2.1/rts/libHSrts.a(Updates.o) >>> referenced by Base.o:(.text+0x3A) in archive /home/user/.ghcup/ghc/9.2.1/lib/ghc-9.2.1/base-4.16.0.0/libHSbase-4.16.0.0.a
已在GHC的settings配置文件中启用-no-pie选项,报错仍存在。
报错根因
- 编译参数中添加的
-fPIC仅对当前项目自行编写的代码生效,GHC 9.2.1版本通过常规包管理器分发的预编译版本中,RTS运行时、base等核心库的静态归档文件(即报错中提到的libHSrts.a、libHSbase-4.16.0.0.a)默认未启用PIC编译,链接生成共享库时就会触发绝对地址重定位不兼容的错误。 - 配置的
-no-pie选项仅对位置无关可执行文件的生成流程生效,对共享库链接阶段没有作用,因此无法解决该问题。 - 输出中的LLVM版本提示为常规警告,GHC 9.2.1实际兼容LLVM 13.0.0版本,不需要额外降级LLVM。
可行解决方法
- 快速解决:按链接器提示追加允许文本段重定位的参数,在GHC编译命令末尾添加
-optl-Wl,-z,notext,将编译配置修改为:
该方案无需改动GHC本身,修改后即可正常完成编译、生成目标bitcode文件,仅在开启了强安全加固策略的环境下可能存在加载限制,适合日常开发、测试场景使用。FILE = lib compile: ghc -fllvm -keep-llvm-files -fforce-recomp -static -shared -flink-rts -fPIC -optl-Wl,-z,notext $(FILE).hs llvm-as $(FILE).ll -o $(FILE).bc - 根治方案:自行编译带全量PIC支持的GHC版本,编译GHC时添加
--with-pic配置参数,保证RTS、所有核心库的静态归档都以PIC模式编译。该方案可以彻底避免这类重定位错误,适合需要长期稳定做GHC-LLVM链路开发的场景,缺点是GHC本身编译耗时较长,对设备性能有一定要求。
内容的提问来源于stack exchange,提问作者Gavin Ray
相关产品推荐
相关产品推荐

