Summary: | x86_64 pe relocation truncated to fit: R_X86_64_PC32 against undefined symbol | ||
---|---|---|---|
Product: | binutils | Reporter: | sourceware-bugzilla |
Component: | ld | Assignee: | Tamar Christina <tnfchris> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | cbiesinger, sourceware.org, ssbssa, tnfchris, vhaisman |
Priority: | P2 | ||
Version: | 2.36 | ||
Target Milestone: | --- | ||
See Also: |
https://github.com/msys2/MINGW-packages/issues/6986 https://github.com/msys2/MINGW-packages/issues/7023 |
||
Host: | Target: | x86_64 pe | |
Build: | Last reconfirmed: | 2021-03-29 00:00:00 | |
Bug Depends on: | |||
Bug Blocks: | 19011 | ||
Attachments: |
testcase source from msys2 #6986
testcase objects from msys2 #6986 |
Description
sourceware-bugzilla
2020-09-23 20:29:24 UTC
There is discussion about this issue in https://github.com/msys2/MINGW-packages/issues/6986 I tested it with GCC 10.2, Binutils 2.35, Clang/LLD 11. Using reproducer in shared.zip by calling ./build.sh (designed to run under MSYS2) GCC+ld.bfd fails with this error: D:\tmp\weak\shared-wiki\build-bfd/../power_slow.c:15:(.text+0x18): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `user_hook' The same code works as expected when using GCC+ld.lld, Clang+ld.bfd, Clang+ld.lld. Extracted details from issue in MSYS2 repo (I couldn't find anything beyond what was already said there): Relocations: Clang: Section (1) .text { 0xB IMAGE_REL_AMD64_REL32 .refptr.user_hook (10) 0x1F IMAGE_REL_AMD64_REL32 .refptr.user_hook (10) 0x4D IMAGE_REL_AMD64_REL32 power2 (24) } GCC: Section (1) .text { 0xE IMAGE_REL_AMD64_REL32 .refptr.user_hook (29) 0x18 IMAGE_REL_AMD64_REL32 user_hook (33) 0x37 IMAGE_REL_AMD64_REL32 power2 (31) } Relevant symbols: Symbol { Name: user_hook Value: 0 Section: IMAGE_SYM_UNDEFINED (0) BaseType: Null (0x0) ComplexType: Function (0x2) StorageClass: WeakExternal (0x69) AuxSymbolCount: 1 AuxWeakExternal { Linked: .weak.user_hook.power3 (30) Search: NoLibrary (0x1) } } Symbol { Name: .rdata$.refptr.user_hook Value: 0 Section: .rdata$.refptr.user_hook (12) BaseType: Null (0x0) ComplexType: Null (0x0) StorageClass: Static (0x3) AuxSymbolCount: 1 AuxSectionDef { Length: 8 RelocationCount: 1 LineNumberCount: 0 Checksum: 0x0 Number: 0 Selection: Any (0x2) } } Symbol { Name: .refptr.user_hook Value: 0 Section: .rdata$.refptr.user_hook (12) BaseType: Null (0x0) ComplexType: Null (0x0) StorageClass: External (0x2) AuxSymbolCount: 0 } Assembly and object file are included in objects.zip. Created attachment 12867 [details]
testcase source from msys2 #6986
Created attachment 12868 [details]
testcase objects from msys2 #6986
Confirmed, this is breaking a lot of projects on Windows including GHC. testing patch. The master branch has been updated by Tamar Christina <tnfchris@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=74edb473c9ecf5e2053ecf8e429ee608feafb9e1 commit 74edb473c9ecf5e2053ecf8e429ee608feafb9e1 Author: Tamar Christina <tamar.christina@arm.com> Date: Thu Apr 1 17:10:38 2021 +0100 PE/Windows x86_64: Fix weak undef symbols after image base change The change in PR19011 changed the image load address from being in the lower 32-bit address space to the higher 64-bit address space. However when you have a weak undef symbol which stays undef at the end of linking the linker has to resolve this (Windows loader does not support undef symbols). As such typically these would resolve to 0. The relocation used for these weak symbols are the normal 32-bit PC_REL call relocs. So when doing the overflow check LD checks if the distance between the symbol and the call is within range. However now that the load address is > 32-bits and the symbol val is 0 this overflow check will always fail. As such the linker gives a bogus error. This patch makes the linker not emit the overflow failure but chooses to still let the check be performed (as it's mid-end code). One down side of this is that it does break the common convention that the call be to sym at 0x0. i.e. before you'd get 401015: 74 05 je 40101c 401017: e8 e4 ef bf ff callq 0 and now you get 140001015: 74 05 je 14000101c 140001017: e8 e4 ef ff bf call 100000000 since the call is PC_REL there's no way to get the range large enough to resolve to 0. As such I have chosen to leave it as the furthest simple range that we can still represent. By only ignoring the error we leave the symbol value itself to still be 0 such that the if(<symbol>) checks still work correctly. bfd/ChangeLog: 2021-04-01 Tamar Christina <tamar.christina@arm.com> PR ld/26659 * cofflink.c (_bfd_coff_generic_relocate_section): Ignore overflow. ld/ChangeLog: 2021-04-01 Tamar Christina <tamar.christina@arm.com> PR ld/26659 * testsuite/ld-pe/pe.exp: Add test. * testsuite/ld-pe/pr26659-weak-undef-sym.d: New test. * testsuite/ld-pe/pr26659-weak-undef-sym.s: New test. The binutils-2_36-branch branch has been updated by Tamar Christina <tnfchris@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=0ff9fad8bf790eebb21a1c1ee378f1c2dd1971af commit 0ff9fad8bf790eebb21a1c1ee378f1c2dd1971af Author: Tamar Christina <tamar.christina@arm.com> Date: Thu Apr 1 17:10:38 2021 +0100 PE/Windows x86_64: Fix weak undef symbols after image base change The change in PR19011 changed the image load address from being in the lower 32-bit address space to the higher 64-bit address space. However when you have a weak undef symbol which stays undef at the end of linking the linker has to resolve this (Windows loader does not support undef symbols). As such typically these would resolve to 0. The relocation used for these weak symbols are the normal 32-bit PC_REL call relocs. So when doing the overflow check LD checks if the distance between the symbol and the call is within range. However now that the load address is > 32-bits and the symbol val is 0 this overflow check will always fail. As such the linker gives a bogus error. This patch makes the linker not emit the overflow failure but chooses to still let the check be performed (as it's mid-end code). One down side of this is that it does break the common convention that the call be to sym at 0x0. i.e. before you'd get 401015: 74 05 je 40101c 401017: e8 e4 ef bf ff callq 0 and now you get 140001015: 74 05 je 14000101c 140001017: e8 e4 ef ff bf call 100000000 since the call is PC_REL there's no way to get the range large enough to resolve to 0. As such I have chosen to leave it as the furthest simple range that we can still represent. By only ignoring the error we leave the symbol value itself to still be 0 such that the if(<symbol>) checks still work correctly. bfd/ChangeLog: 2021-04-01 Tamar Christina <tamar.christina@arm.com> PR ld/26659 * cofflink.c (_bfd_coff_generic_relocate_section): Ignore overflow. ld/ChangeLog: 2021-04-01 Tamar Christina <tamar.christina@arm.com> PR ld/26659 * testsuite/ld-pe/pe.exp: Add test. * testsuite/ld-pe/pr26659-weak-undef-sym.d: New test. * testsuite/ld-pe/pr26659-weak-undef-sym.s: New test. (cherry picked from commit 74edb473c9ecf5e2053ecf8e429ee608feafb9e1) Fixed in mainline and 2.36. The master branch has been updated by Jan Beulich <jbeulich@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d018cd835ccdbfcfbc1e144a836974a9b9c385b6 commit d018cd835ccdbfcfbc1e144a836974a9b9c385b6 Author: Jan Beulich <jbeulich@suse.com> Date: Thu Apr 22 10:55:07 2021 +0200 x86-64/PE: adjust PR ld/26659 testcase for Cygwin While the testcase put in place by 74edb473c9ec ("PE/Windows x86_64: Fix weak undef symbols after image base change") is fine for MingW, it fails for Cygwin. This is because the default image base is different there (for whatever reason). |