LLVM generated object files should have their relocatable `.data.rel.ro` sections writable
Summary
Currently, the LLVM code generator can produce code with relocatable data in read-only .data.rel.ro
sections. Those sections should be writable when building code. They will be protected once relocation has been done at the execution of the built program by the C runtime.
The reasons for marking those sections writable in GHC would be:
- Conformity with the Linux Standard Base Core specifications
- Tooling flexibility (i.e. GHC being as independent as possible from specific tools and/or tool versions)
For the latter reason, because GHC produce code with read-only relocatable sections, what comes after it has to mark them as writable. The GNU assembler does that. So in a sense, there's a dependency to it. Is that voluntary? In any case, GHC might as well produce valid code as soon as possible.
The current LLVM pipeline uses the GNU assembler that automatically marks the .data.rel.ro
sections as writable. The GNU ld does as well. Removing those could potentially result in segfaults (see #18076 (closed)). The gold linker does not enforce those sections to be writable so the resulting executables won't be valid.
That being said, the problem could only be observed with the deprecated -fast-llvm
(see !3120 (closed)) flag and the gold linker. The problem cannot be reproduced with the Native Code Generator (it seems that it doesn't describe those sections, apart from the name, so the GNU assembler might just assume it is writable).
Steps to reproduce
- Create a simple
RelocRoData.hs
Haskell module with the following content:
module RelocRoData
( SomeData(..)
)
where
data SomeData = SomeConstr
- Run
inplace/bin/ghc-stage2 -v -split-sections -fllvm -c RelocRoData.hs -keep-tmp-files
(the sections of interest are only generated with the-split-sections
flag) - Run
grep data.rel.ro ghc_4.lm_s
(whereghc_4.lm_s
is actually the path to the generated Assembler file after mangling)
Observe the following output:
.section .data.rel.ro.RelocRoData_SomeData_closure_tbl,"a",@progbits
Expected behavior
Following the previous instruction, we should observe:
.section .data.rel.ro.RelocRoData_SomeData_closure_tbl,"aw",@progbits
There should be the w
indicating that the .data.rel.ro
section is writable.
Environment
- GHC version used: 8.6.5 (as cross-compiler from x86_64 to armv6l, 8.11.0 (latest master version, on x86_64)
- NixOS 19.09
Implementations
There's an initial (rather quick) implementation as a Haskell.nix patch. Manual testing confirmed it worked when producing armv6l programs with the deprecated fast-llvm
flag (GHC 8.6.5).
I'm currently creating a PR in GHC. Without the fast-llvm
flag, the issue can only be observed in the intermediary files, which is not ideal.