Bugzilla – Bug 5004
Bootstrap failure "Error: can not do 8 byte pc-relative relocation"
Last modified: 2010-02-09 06:46:09
You need to log in before you can comment on or make changes to this bug.
Using llvm r82173 and gcc 4.2.1 20070719 as the host compiler the bootstrap of llvm-gcc r82176 fails to bootstrap on FreeBSD/amd64 8.0 /usr/src-local/llvm-gcc/obj/./gcc/xgcc -shared-libgcc -B/usr/src-local/llvm-gcc/obj/./gcc -nostdinc++ -L/usr/src-local/llvm-gcc/obj/x86_64-unknown-freebsd8.0/libstdc++-v3/src -L/usr/src-local/llvm-gcc/obj/x86_64-unknown-freebsd8.0/libstdc++-v3/src/.libs -B/opt/llvm-gcc/x86_64-unknown-freebsd8.0/bin/ -B/opt/llvm-gcc/x86_64-unknown-freebsd8.0/lib/ -isystem /opt/llvm-gcc/x86_64-unknown-freebsd8.0/include -isystem /opt/llvm-gcc/x86_64-unknown-freebsd8.0/sys-include -I/usr/src-local/llvm-gcc/libstdc++-v3/../gcc -I/usr/src-local/llvm-gcc/obj/x86_64-unknown-freebsd8.0/libstdc++-v3/include/x86_64-unknown-freebsd8.0 -I/usr/src-local/llvm-gcc/obj/x86_64-unknown-freebsd8.0/libstdc++-v3/include -I/usr/src-local/llvm-gcc/libstdc++-v3/libsupc++ -fno-implicit-templates -Wall -Wextra -Wwrite-strings -Wcast-qual -fdiagnostics-show-location=once -ffunction-sections -fdata-sections -g -O2 -c ../../../../libstdc++-v3/libsupc++/eh_alloc.cc -o eh_alloc.o /var/tmp//ccEBSLfL.s: Assembler messages: /var/tmp//ccEBSLfL.s:757: Error: can not do 8 byte pc-relative relocation /var/tmp//ccEBSLfL.s:772: Error: can not do 8 byte pc-relative relocation /var/tmp//ccEBSLfL.s:793: Error: can not do 8 byte pc-relative relocation gmake[4]: *** [eh_alloc.lo] Error 1 gmake[4]: Leaving directory `/usr/src-local/llvm-gcc/obj/x86_64-unknown-freebsd8.0/libstdc++-v3/libsupc++'
Please attach the LLVM IR. I doubt anyone who can look ino the problem has FreeBSD around.
Please attach both the LLVM IR and the .s file, thanks.
Created an attachment (id=3534) [details] eh_alloc.bc
Created an attachment (id=3535) [details] eh_alloc.s
This bug is now also seen with the 2.6-PRE2 release, PRE1 did not have this problem. I've attached both the assembly and LLVM IR.
This is a 2.6 release blocker. Is someone working on it or do we need to recruit more people?
Pawel, please include the output of running 'gcc -c eh_alloc.s' on the .s file. The line numbers above don't line up.
Actually, running 'gcc -m64 eh_alloc.s -c' on a linux system assembled the file just fine. Are you sure there is a problem here?
Pawel - Any updates?
Expect an update within two hours, I'm updating my trunk build of llvm now. The IR and ASM was the output from 2.6, sorry for not attaching the output, this was the reason the lines probably didn't line up.
# gcc -c eh_alloc.s eh_alloc.s: Assembler messages: eh_alloc.s:774: Error: can not do 8 byte pc-relative relocation eh_alloc.s:789: Error: can not do 8 byte pc-relative relocation binutils is 2.15 Build output from trunk: /usr/src-local/llvm-gcc/obj/./gcc/xgcc -shared-libgcc -B/usr/src-local/llvm-gcc/obj/./gcc -nostdinc++ -L/usr/src-local/llvm-gcc/obj/x86_64-unknown-freebsd8.0/libstdc++-v3/src -L/usr/src-local/llvm-gcc/obj/x86_64-unknown-freebsd8.0/libstdc++-v3/src/.libs -B/opt/llvm-gcc/x86_64-unknown-freebsd8.0/bin/ -B/opt/llvm-gcc/x86_64-unknown-freebsd8.0/lib/ -isystem /opt/llvm-gcc/x86_64-unknown-freebsd8.0/include -isystem /opt/llvm-gcc/x86_64-unknown-freebsd8.0/sys-include -I/usr/src-local/llvm-gcc/libstdc++-v3/../gcc -I/usr/src-local/llvm-gcc/obj/x86_64-unknown-freebsd8.0/libstdc++-v3/include/x86_64-unknown-freebsd8.0 -I/usr/src-local/llvm-gcc/obj/x86_64-unknown-freebsd8.0/libstdc++-v3/include -I/usr/src-local/llvm-gcc/libstdc++-v3/libsupc++ -fno-implicit-templates -Wall -Wextra -Wwrite-strings -Wcast-qual -fdiagnostics-show-location=once -ffunction-sections -fdata-sections -g -O2 -c ../../../../libstdc++-v3/libsupc++/eh_alloc.cc -o eh_alloc.o /var/tmp//ccM0T20x.s: Assembler messages: /var/tmp//ccM0T20x.s:774: Error: can not do 8 byte pc-relative relocation /var/tmp//ccM0T20x.s:789: Error: can not do 8 byte pc-relative relocation gmake[4]: *** [eh_alloc.lo] Error 1 gmake[4]: Leaving directory `/usr/src-local/llvm-gcc/obj/x86_64-unknown-freebsd8.0/libstdc++-v3/libsupc++' gmake[3]: *** [all-recursive] Error 1 gmake[3]: Leaving directory `/usr/src-local/llvm-gcc/obj/x86_64-unknown-freebsd8.0/libstdc++-v3' gmake[2]: *** [all] Error 2 gmake[2]: Leaving directory `/usr/src-local/llvm-gcc/obj/x86_64-unknown-freebsd8.0/libstdc++-v3' gmake[1]: *** [all-target-libstdc++-v3] Error 2 gmake[1]: Leaving directory `/usr/src-local/llvm-gcc/obj' gmake: *** [bootstrap] Error 2
Created an attachment (id=3552) [details] eh_alloc.bc from trunk
Created an attachment (id=3553) [details] eh_alloc.s from trunk
It looks like freebsd (or that version of gas) doesn't support that relocation type. This code seems to be to blame in DwarfException.cpp: // If there is a personality and landing pads then point to the language // specific data area in the exception table. if (MMI->getPersonalities()[0] != NULL) { bool is4Byte = TD->getPointerSize() == sizeof(int32_t); Asm->EmitULEB128Bytes(is4Byte ? 4 : 8); Asm->EOL("Augmentation size"); if (EHFrameInfo.hasLandingPads) EmitReference("exception", EHFrameInfo.Number, true, false); Pawel, if you force "is4Byte" to true, does it work for you?
Created an attachment (id=3557) [details] eh_alloc.bc from 2.6
Created an attachment (id=3558) [details] eh_alloc.s from 2.6
I should have said that the last two attachments are from 2.6-PRE1 that builds ok.
This is generic problem in our dwarf asmprinting, which seems currently to be pretty darwin-centric. The problem is that we're emitting pcrel reference to EH frame. This is ok only for darwin. For linux we should use absptr / udata4 depending on the codemodel. 8 byte pcrel relocations should be used only for large / kernel code models (and in PIC mode only). This is actually both optimization & correctness stuff. Optimization: the section is placed at zero address, thus pcrel relocations are generally not neeeded. Also they are quite big... Correctness: 8 byte pcrel relocations were added only in binutils 2.17 The deleted EHFreferredDataFormat hooks returned proper encoding in all the cases. We need to restore them and implement generic reference printing routine (for given encoding).
Proposed solution: 1. Implement MAI hooks for returning target-specific personality / fde / lsda encodings 2. Extend EmitReference stuff to work with encodings, not with bunch of flags (indirect / force32 bit) 3. Use encodings consistently across the code (currently we're emitting encodings & handle reference printing separately effectively duplicating the stuff) Estimated time to implement: 2-4 hours Pros: Obvious Cons: need extra round of tests :(
(In reply to comment #19) > Proposed solution: > > 1. Implement MAI hooks for returning target-specific personality / fde / lsda > encodings Actually, we need to think about proper way, since encoding (at least on linux) depends on relocation model & code model. This should not be exposed via MAI
Ok, this is no longer blocking 2.6. This is going to require some invasive surgery and needs to be baked. For 2.6 we should recommend that people upgrade their binutils if they run into this. I'll update the release notes to mention it.
llvm-gcc also has this problem on OpenBSD/amd64 for what it's worth. Currently an older version of binutils (2.15) is used which doesn't have R_X86_64_SIZE64. There are plans to update binutils but this is a lot of work to catch breakage on all the supported platforms and fix it.
recently I started seeing this with clang++: pes ~$ cat catch.cc void bar(void); void foo(void) { try { bar(); } catch (...) { } } pes ~$ clang++ catch.cc /tmp/cc-wXOL0W.s: Assembler messages: /tmp/cc-wXOL0W.s:138: Error: can not do 8 byte pc-relative relocation clang: error: assembler command failed with exit code 1 (use -v to see invocation) pes ~$ is it the same issue as described here? if so is there any progress with this? (this is blocking llvm compilation with clang for example)
*** Bug 5977 has been marked as a duplicate of this bug. ***
Created an attachment (id=4136) [details] patch to fix LSDA encoding in the CIE generated by the LLVM JIT.
Created an attachment (id=4141) [details] Preliminary patch Here is preliminary patch to try. It implements: - Hooks to return Personality / FDE / LSDA / TType encoding depending on target / options (e.g. code model / relocation model) - MCIzation of Dwarf EH printer to use encoding information - Stub generation for ELF target (needed for indirect references) - Some other small changes here and there Tested on x86-32 and x86-64 linux. Not tested on darwin.
The patch looks pretty good, llvm-gcc bootstraps (c,c++), a lot of previously broken c++ apps in FreeBSD now build. clang self-builds to the point of a link failure.
(In reply to comment #26) > Created an attachment (id=4141) [details] [details] > Preliminary patch This patch is close: $ cat picfail.m #import <objc/Object.h> #import <objc/NXConstStr.h> int main(void) { @try { @throw(@"foo"); } @catch(Object *a) {} return 0; } $ clang -fPIC picfail.m /tmp/cc-Qugv3L.s: Assembler messages: /tmp/cc-Qugv3L.s:311: Error: symbol `.L__unnamed_1' is already defined clang: error: assembler command failed with exit code 1 (use -v to see invocation) The EH data seems correct, the address is now: .long .L__unnamed_1-. This is what gcc emits, while clang previously generated this: .long .L__unnamed_1 (Where .L__unnamed_1 is "Object") However, at the end of the file I find this: .section .note.GNU-stack,"",@progbits .section .data.rel,"aw",@progbits .L__gnu_objc_personality_v0: .long __gnu_objc_personality_v0 .L__unnamed_1: .long .L__unnamed_1 This second definition of .L__unnamed_1 is breaking things. The reference to the personality function also looks very different. This appears to be a regression; the unwind library was correctly finding the personality function with the old version, now it is failing to. There seem to be a number of changes to the EH frame. Before the change: .byte 0x1B .long __gnu_objc_personality_v0-. After: .byte 155 .long .L__gnu_objc_personality_v0-. It's a bit difficult to play spot the difference because you've made it emit decimal, rather than hex, values for the constants, however, note that the value of the byte immediately preceding the address of the personality function changed from 27 to 155 as a result of this patch. I'm not sure what this change means - I can't find the ABI docs - but reverting this in the generated assembly cause it to enter the personality routine. Unfortunately, it still crashes in the part of the personality function that tries to read .L__unnamed_1. The rest of the exception frame looks totally different in GCC. I can provide you with the assembled versions of both if you like, or you can generate them by compiling the trivial example from above with gcc and clang.
(In reply to comment #28) > This second definition of .L__unnamed_1 is breaking things. Ok, this makes sense. Stub generation should be improved to honour private symbols properly. > changed from 27 to 155 as a result of this patch. I'm not sure what this > change means - I can't find the ABI docs That's correct change. We need to use indirect pcrel encoding in general. > The rest of the exception frame looks totally different in GCC. This is surely expected.
(In reply to comment #29) > (In reply to comment #28) > > changed from 27 to 155 as a result of this patch. I'm not sure what this > > change means - I can't find the ABI docs > That's correct change. We need to use indirect pcrel encoding in general. Yes, you're right, the problem is elsewhere. Looking at the GCC output, it uses the same value, then: .long DW.ref.__gnu_objc_personality_v0-. This is basically the same as clang is now emitting: .long .L__gnu_objc_personality_v0-. However, the definition looks quite different GCC emits this: .hidden DW.ref.__gnu_objc_personality_v0 .weak DW.ref.__gnu_objc_personality_v0 .section .gnu.linkonce.d.DW.ref.__gnu_objc_personality_v0,"aw",@progbits .align 4 .type DW.ref.__gnu_objc_personality_v0, @object .size DW.ref.__gnu_objc_personality_v0, 4 DW.ref.__gnu_objc_personality_v0: .long __gnu_objc_personality_v0 LLVM emits this: .section .note.GNU-stack,"",@progbits .section .data.rel,"aw",@progbits .L__gnu_objc_personality_v0: .long __gnu_objc_personality_v0 I'm not sure what the two .section directives are supposed to be for, but deleting them fixes the problem. If I rename the second L__unnamed_1 to L__unnamed_2 in both places where it is used, then after deleting the two section directives (are they C++ specific?) the catch handler finds the correct object and the test program exits correctly. So, removing the section stuff and correctly naming new variables should fix this patch.
(In reply to comment #30) > So, removing the section stuff The section shouldn't matter at all! Both are emitted into data section. What if you add type/size stuff to llvm-generated one?
Created an attachment (id=4147) [details] Updated patch Here is updated patch. It contains two additional fixes: - Suffix is added for stubs, so we don't have name clash with private symbols anymore - I realized that we emitted invalid common eh frame since the early beginning - augmentation size uleb was emitted even if augmentation string indicated that there was no such word. This lead to invalid frame moves emission.
(In reply to comment #32) > Created an attachment (id=4147) [details] [details] > Updated patch > > Here is updated patch. It contains two additional fixes: > - Suffix is added for stubs, so we don't have name clash with private symbols > anymore > - I realized that we emitted invalid common eh frame since the early beginning > - augmentation size uleb was emitted even if augmentation string indicated that > there was no such word. This lead to invalid frame moves emission. > This version works perfectly for me (FreeBSD, IA32). Exceptions can now be caught in both PIC code and non-PIC code. Thanks! > The section shouldn't matter at all! Both are emitted into data section. What > if you add type/size stuff to llvm-generated one? They don't seem to matter in the new version.
We should test this on darwin before committing. If anyone can that would be appreciated, otherwise i'll look at it shortly.
Applying the patch (and cleaning it up a bit to resolve some patch rejections and removing some "const"s) results in this cyclic dependency during compilation: llvm[1]: Checking for cyclic dependencies between LLVM libraries. find-cycles.pl: Circular dependency between *.a files: find-cycles.pl: libLLVMAnalysis.a libLLVMCodeGen.a libLLVMTarget.a
Created an attachment (id=4207) [details] Patch against ToT Here is new patch against ToT. Chris changes MC-related stuff too fast ;)
(In reply to comment #35) > llvm[1]: Checking for cyclic dependencies between LLVM libraries. > find-cycles.pl: Circular dependency between *.a files: > find-cycles.pl: libLLVMAnalysis.a libLLVMCodeGen.a libLLVMTarget.a Seems to be bogus. No Analysis code is touched. Which symbol(s) causes the cycle?
(In reply to comment #37) > (In reply to comment #35) > > llvm[1]: Checking for cyclic dependencies between LLVM libraries. > > find-cycles.pl: Circular dependency between *.a files: > > find-cycles.pl: libLLVMAnalysis.a libLLVMCodeGen.a libLLVMTarget.a > Seems to be bogus. No Analysis code is touched. Which symbol(s) causes the > cycle? > No clue. How do I find this out? There is a genuine cycle: libLLVMAnalysis.a: libLLVMCore.a libLLVMSupport.a libLLVMSystem.a libLLVMTarget.a libLLVMCodeGen.a: libLLVMAnalysis.a libLLVMCore.a libLLVMMC.a libLLVMScalarOpts.a libLLVMSupport.a libLLVMSystem.a libLLVMTarget.a libLLVMTransformUtils.a libLLVMTarget.a: libLLVMCodeGen.a libLLVMCore.a libLLVMMC.a libLLVMSupport.a
(In reply to comment #38) > There is a genuine cycle: > > libLLVMAnalysis.a: libLLVMCore.a libLLVMSupport.a libLLVMSystem.a > libLLVMTarget.a > > libLLVMCodeGen.a: libLLVMAnalysis.a libLLVMCore.a libLLVMMC.a > libLLVMScalarOpts.a libLLVMSupport.a libLLVMSystem.a libLLVMTarget.a > libLLVMTransformUtils.a > > libLLVMTarget.a: libLLVMCodeGen.a libLLVMCore.a libLLVMMC.a libLLVMSupport.a > Without the change, here are the dependencies: libLLVMAnalysis.a: libLLVMCore.a libLLVMSupport.a libLLVMSystem.a libLLVMTarget.a libLLVMCodeGen.a: libLLVMAnalysis.a libLLVMCore.a libLLVMMC.a libLLVMScalarOpts.a libLLVMSupport.a libLLVMSystem.a libLLVMTarget.a libLLVMTransformUtils.a libLLVMTarget.a: libLLVMCore.a libLLVMMC.a libLLVMSupport.a So the libLLVMTarget.a is picking up libLLVMCodeGen.a stuff.
(In reply to comment #38) > No clue. How do I find this out? iirc there was some option -why of that script which shows the symbol... > There is a genuine cycle: > > libLLVMAnalysis.a: libLLVMCore.a libLLVMSupport.a libLLVMSystem.a > libLLVMTarget.a This seems to be strange... Why would analysis require codegen?
(In reply to comment #39) > So the libLLVMTarget.a is picking up libLLVMCodeGen.a stuff. Well, this is definitely expected, since target uses MMI (via TargetObjectLowering). But... I have this on linux: libLLVMTarget.a: libLLVMCore.a libLLVMMC.a libLLVMSupport.a :(
(In reply to comment #40) > > libLLVMAnalysis.a: libLLVMCore.a libLLVMSupport.a libLLVMSystem.a > > libLLVMTarget.a > This seems to be strange... Why would analysis require codegen? Seems to be due to profile stuff, which pulls MachineBasicBlock and MachineFunction. Should that pass really be there?