x86_64 (cross)compiler with -fPIC produces R_X86_64_PC32 relocations that don't work for ld -shared.
That's required on the Haiku platform: executables must be linked with -shared. I know nothing about this, but ...
only some R_X86_64_PC32 relocations fail, while others that appear in objdump -r output seem to be normal.
some of the offending symbols appear in assembler output:
leaq base_DataziTuple_swap_closure(%rip),%rbx
the working native C compiler writes this to load a function address, producing an acceptable R_X86_64_REX_GOTPCRELX relocation:
movq testfunction@GOTPCREL(%rip), %rax
movq %rax, %rdi
Steps to reproduce
link compiled files with features like base_DataziTuple_swap_closure, on ELF platform, with collect2/ld -shared option.
Expected behavior
ld: Tuple.o: relocation R_X86_64_PC32 against symbol `base_DataziTuple_swap_closure' can not be used when making a shared object; recompile with -fPICld: final link failed: bad value
8.6.3 stage1 cross compiler, built and running on i386; as far as I'm able to get 8.8.1, it generates the same code, so I expect it to have the same problem if I can compile it.
Environment
GHC version used: 8.6.3
Optional:
Operating System: Haiku
System Architecture: i386 / x86_64
Edited
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Child items
0
Show closed items
No child items are currently assigned. Use child items to break down this issue into smaller parts.
Linked items
0
Link issues together to show that they're related or that one is blocking others.
Learn more.
Hmm, I'm not really sure what to say about this. We rely on the assembler to do the right thing when producing relocations. I'm pretty sure we inform the assembler that we want relocatable code lest things would be breaking left and right. Which compiler toolchain are you using?
I checked "as", many options, but nothing about PIC, pic, position, etc.
This is what I could make out of what I read in online discussions of this matter. If you produce that assembly language, on X86_64 ELF, it won't be share-able - not because you forgot to ask the assembler to do it, it's the code that does it. Compilers produce different code for -fPIC. If they do it right, it works, and the assembled output is share-able. That is about as much as I know, and "know" is of course stretching it. I did go so far as to write some simple C and change the @GOTPCREL part to more like what GHC does, with same result - ld fails. If you contrive to load with ld -shared, I expect you will find the same, on X86_64 ELF.
I do wonder whether this is due to our assumption of a small memory model on x86-64, even when compiling with -fPIC (at least I believe this is the assumption; @simonmar, is this your understanding as well?)
For the record, the following is sufficient to reproduce this:
$ cat hi.hsimport Data.Tuplemain = print $ swap (4,5)$ _build/stage1/bin/ghc -O0 hi.hs -optl-shared -dynamic -fPICLinking hi .../nix/store/zizh5qzhcn4wzm06z99297ckalwrrpfk-binutils-2.31.1/bin/ld: hi.o: relocation R_X86_64_PC32 against symbol `Main_main_closure' can not be used when making a shared object; recompile with -fPIC/nix/store/zizh5qzhcn4wzm06z99297ckalwrrpfk-binutils-2.31.1/bin/ld: final link failed: bad valuecollect2: error: ld returned 1 exit status`cc' failed in phase `Linker'. (Exit code: 1)
Here's how the ghc-stage1 compiler build was configured.
---- number of usual patches, among which only this one might be relevant,in compiler.main.DriverPipeline.hs: joinObjectFiles ld_r,I add SysTools.Option "-r" to the SysTools.runLink options list.Have always needed this on Haiku.-- build.mk (where different from build.mk.sample):BUILD_PROF_LIBS = NOHADDOCK_DOCS = NOBUILD_SPHINX_HTML = NOBUILD_SPHINX_PDF = NOBUILD_MAN = NOWITH_TERMINFO = NOINTEGER_LIBRARY = integer-simple-- config.mk:DYNAMIC_GHC_PROGRAMS = NODYNAMIC_TOO=NO[ deconfigure GhcLibWays p ]SRC_HC_OPTS_STAGE1 = -fPIC-> configure --target=x86_64.unknown.haiku-- project.mk excerpts:HOSTPLATFORM = i386-unknown-haikuTARGETPLATFORM = x86_64-unknown-haikuBUILDPLATFORM = i386-unknown-haikuHostPlatform_CPP = i386_unknown_haikuHostArch_CPP = i386HostOS_CPP = haikuHostVendor_CPP = unknownTargetPlatform_CPP = x86_64_unknown_haikuTargetArch_CPP = x86_64TargetOS_CPP = haikuTargetVendor_CPP = unknownLLVMTarget_CPP = x86_64-unknown-haikuBuildPlatform_CPP = i386_unknown_haikuBuildArch_CPP = i386BuildOS_CPP = haikuBuildVendor_CPP = unknown...CC_LLVM_BACKEND = 0CC_CLANG_BACKEND = 0----
The build fails when ghc-stage1 tries to link hsc2hs, with this error:
/boot/home/haiku64/boot/system/develop/tools/bin/../lib/gcc/x86_64-unknown-haiku/8.3.0/../../../../x86_64-unknown-haiku/bin/ld.bfd: utils/hsc2hs/dist-install/build/Main.o: relocation R_X86_64_PC32 against symbol `ghczmprim_GHCziTypes_False_closure' can not be used when making a shared object; recompile with -fPIC
I make no pretense of understanding what I see here. After that, I went to the x86_64 host and made some experiments on simple native compiled C, which I have presented above as evidence that this is the outcome of the instructions produced by the compiler, - mov vs. lea, the symbol@GOTPCREL notation etc.; here presumably the mov %rax,%rdi / lea 0x0(%rip),%rsi that appears in the objdump assembly.
It has been going on here for several years, going back at least to GHC 7.4.2, and the other occasional Haiku effort for GHC does this also. But naturally I don't remember the details. If it seems like this might be an obstacle, I can try to build GHC without this edit and report what happens. I think it's clear enough though that it would have no effect on code generation?
Well, coming back to this again. I managed to compile an unregisterised GHC for Haiku x86_64, but building GHC on Haiku itself, the same as when cross-compiling, is generating the same issue.
Looking in detail, the problem appears to be with the data tables GHC seems to generate, as described in cmm/CLabel.hs, e.g. the "Static closure" and "Dynamic Constructor info table", probably a few others.
I am currently using 8.6.5, as building a cross-compiled GHC still worked reliably then, but the error has remained in newer versions of GHC when cross-compiling.
Interestingly, the stage1 compiler runs fine, but building the stage2 compiler fails.
@jessicah, thanks for the clear reproducer. Just to be clear that we are on the same page, do you suppose you could update your comment to point out precisely where you see the problems here.
From the error I suspect the problem is the use of %rip-relative references (e.g. to stg_bh_upd_frame_info and many others). However, I also wonder whether the absolute inter-object references (e.g. to base_GHCziTopHandler_runMainIO_closure) in u1ui_srt and r1hf_closure are similarly problematic. Perhaps we are saved by the fact that these are located in .data sections
In the case of the %rip-relative references, I suspect these should rather be GOT-indirected %rip-relative references (e.g. R_X86_64_REX_GOTPCRELX). The assembler syntax for this is foo@GOTPCREL(%rip).
@jessicah looking more carefully at your invocation, it seems that you didn't pass -fPIC to _build/stage1/bin/ghc; was this an oversight? If your platform requires PIC by default then perhaps it would be useful to add a rule in GHC.Driver.DynFlags.default_PIC.
In the original issue text, in point 3, I tried making edits to the generated temporary files similar to what was described:
the working native C compiler writes this to load a function address, producing an acceptable R_X86_64_REX_GOTPCRELX relocation:
movq testfunction@GOTPCREL(%rip), %rax
movq %rax, %rdi
It made the compiler errors go away, but there were further instances of a different form also happening, I think in the data sections, I can't recall, I'd have to redo.
E.g. rewriting leaq ghczmprim_GHCziCString_unpackCStringzh_closure(%rip),%rbx to use GOTPCREL helped with compile issues.
I think the data section issues were instances such as .quad ghczmprim_GHCziCString_unpackCStringzh_closure?
Unregisterised builds are available at https://github.com/jessicah/haiku-ghc/releases, but the issue also happens when cross-compiling (of which only 8.6.5 works as stated earlier). I have natively built newer versions of unregisterised GHC on Haiku, up to 9.4.
It would be interesting to see the generated temporary assembly file for a basic hello world example compiled for OSDarwin, to see how the relocations may differ, if someone can provide that.