HaskellR icon indicating copy to clipboard operation
HaskellR copied to clipboard

R_hsc_make.o: requires dynamic R_X86_64_32 reloc which may overflow at runtime; recompile with -fPIC

Open UnkindPartition opened this issue 3 years ago • 3 comments

On Fedora (35; but I had the same issue back on 33), I get the following error when trying to build inline-r without nix:

error: /usr/bin/ld.gold: error: .stack-work/dist/x86_64-linux-tinfo6/Cabal-3.4.1.0/build/Foreign/R_hsc_make.o: requires dynamic R_X86_64_32 reloc which may overflow at runtime; recompile with -fPIC
collect2: error: ld returned 1 exit status

Apparently, this is caused by gcc using pie (position-independent executables) as a security feature by default, and is fixed on the ghc side by passing -no-pie to gcc. However, hsc2hs calls gcc directly and doesn't know to pass -no-pie; see https://github.com/haskell/hsc2hs/issues/66. I'm not entirely sure this is the correct diagnosis, but it looks plausible.

Environment

  • Fedora 35
  • Version of the code: c3ba1023480e26ade420896bcb629ceaad59f308

UnkindPartition avatar Feb 21 '22 11:02 UnkindPartition

FWIW, I tried changing my /home/roman/.stack/programs/x86_64-linux/ghc-tinfo6-9.0.2/bin/hsc2hs script by adding

HSC2HS_EXTRA=" --lflag=-fuse-ld=gold --cflag=-no-pie"

and that didn't make any difference. It's hard to observe how these options propagate from one program to another using strace because they use the @file option passing heavily, but at the end collect2 is still called with -pie.

UnkindPartition avatar Feb 21 '22 12:02 UnkindPartition

See https://github.com/tweag/HaskellR/issues/257. In more detail, what's happening here is that on Fedora, packages on hardened by default. Binaries are built as PIE's. But it's not GCC doing that behind people's back. It's the pkg-config database telling consumers of any library in these packages to use the hardening flags. And worse, they can't be overridden.

On Fedora, there is a set of macros for RPM's in /lib/rpm/redhat/macros. One of them is called %build_ldflags. It references a spec file called /usr/lib/rpm/redhat/redhat-hardened-ld that adds -pie to the linker's command line in most cases, whether -no-pie was specified by the user or not. As a result, you can link a binary as PIE or not a PIE if you call gcc directly. But if you depend on R, or any other RPM, then Cabal will pick the spec file mentioned above, pass that to GHC, which in turn passes it to the linker. So binaries built by Cabal are always PIE's if they depend on a system library pulled from the pkg-config database.

The hsc2hs error you're seeing above is because hsc2hs as part of the pre-processing it does tries to build an executable. This executable must be a PIE, since hsc2hs inherits the same flags as GHC. But hsc2hs doesn't know this and produces static, non-PIC code that can't be linked into the PIE. You can workaround this using hsc2hs-options: --cflag=-fPIC, but this requires Cabal>=3.6 and therefore a recent cabal-install or Stack.

Then GHC, like hsc2hs, assumes it's producing non-PIE binaries, except that the spec file forces the output to be PIE anyway. So you'll get other linker errors when linking any binary that depends on inline-r (and transitively libR.so). The workaround there is the same as already mentioned in #257: add -dynamic to the ghc-options field for each executable in the Cabal file (including test binaries). This flag tells GHC to use shared libraries when linking and therefore code that is relocatable if not PIC.

So I'd close as a dupe of #257, except that we could probably improve the FAQ entry about this. Either that or force the use of -dynamic everywhere, which is not ideal, but then at least behaviour is uniform across distros.

mboes avatar Nov 01 '22 22:11 mboes

(BTW I don't think rpm is involved here? Perhaps you mean the Fedora R package build configuration is "leaking"?)

I seem to be hitting something similar on Ubuntu 22.04 using debian11 ghc 9.4.4. When attempting to build for Stackage Nightly:

       Preprocessing test suite 'tests' for inline-r-1.0.0..                                                                        
       Building test suite 'tests' for inline-r-1.0.0..                                                                             
       [1 of 8] Compiling Test.Constraints                                                                                          
       [2 of 8] Compiling Test.Event                                                                                                
       [3 of 8] Compiling Test.FunPtr                                                                                               
       [4 of 8] Compiling Test.GC                                                                                                   
       [5 of 8] Compiling Test.Matcher                                                                                              
       [6 of 8] Compiling Test.Regions                                                                                              
       [7 of 8] Compiling Test.Vector                                                                                               
       [8 of 8] Compiling Main                                                                                                      
       [9 of 9] Linking .stack-work/dist/x86_64-linux-tinfo6/Cabal-3.8.1.0/build/tests/tests                                        
       Preprocessing benchmark 'bench-qq' for inline-r-1.0.0..                                                                      
       Building benchmark 'bench-qq' for inline-r-1.0.0..                                                                           
       [1 of 1] Compiling Main                                                                                                      
       [2 of 2] Linking .stack-work/dist/x86_64-linux-tinfo6/Cabal-3.8.1.0/build/bench-qq/bench-qq                                  
       Preprocessing test suite 'test-qq' for inline-r-1.0.0..                                                                      
       Building test suite 'test-qq' for inline-r-1.0.0..                                                                           
       [1 of 1] Compiling Main                                                                                                      
       [2 of 2] Linking .stack-work/dist/x86_64-linux-tinfo6/Cabal-3.8.1.0/build/test-qq/test-qq                                    
       Preprocessing benchmark 'bench-hexp' for inline-r-1.0.0..                                                                    
       Building benchmark 'bench-hexp' for inline-r-1.0.0..                                                                         
       [1 of 1] Compiling Main                                                                                                      
       [2 of 2] Linking .stack-work/dist/x86_64-linux-tinfo6/Cabal-3.8.1.0/build/bench-hexp/bench-hexp                              

       Preprocessing test suite 'test-shootout' for inline-r-1.0.0..                                                                
       Building test suite 'test-shootout' for inline-r-1.0.0..                                                                     
       [1 of 2] Compiling Test.Scripts                                                                                              
       [2 of 2] Compiling Main                                                                                                      
       /usr/bin/ld.gold: error: .stack-work/dist/x86_64-linux-tinfo6/Cabal-3.8.1.0/build/test-shootout/test-shootout-tmp/Test/Script
s.dyn_o: requires dynamic R_X86_64_PC32 reloc against 'TestziScripts_scripts10_bytes' which may overflow at runtime; recompile with 
-fPIC                                                                                                                               
       collect2: error: ld returned 1 exit status                                                                                   
                                                                                                                                    
       <no location info>: error:                                                                                                   
           `gcc' failed in phase `Linker'. (Exit code: 1)

On the other hand the rest of the testsuite is linking: so should I open a separate issue for this? (This started while upgrading the Stackage Nightly build to ghc-9.4.4 and together with moving from Ubuntu 20.04 to 22.04.)

From perusing SO, the only way to fix this seems to be -fPIC, but I haven't dug into #257 in detail. What is special about R here?

juhp avatar Jan 01 '23 02:01 juhp