Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
UnkindPartition opened this issue Feb 21, 2022 · 3 comments

Comments

@UnkindPartition
Copy link
Collaborator

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 haskell/hsc2hs#66. I'm not entirely sure this is the correct diagnosis, but it looks plausible.

Environment

  • Fedora 35
  • Version of the code: c3ba102
@UnkindPartition
Copy link
Collaborator Author

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.

@mboes
Copy link
Member

mboes commented Nov 1, 2022

See #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.

@juhp
Copy link

juhp commented Jan 1, 2023

(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 added a commit to commercialhaskell/stackage that referenced this issue Jan 1, 2023
       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)
juhp added a commit to commercialhaskell/stackage that referenced this issue Jun 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants