On 64-bit Windows, when calculating a 64-bit address difference between two labels in different sections, the value will be off. This program should not abort, but it does: .text .intel_syntax noprefix c: .quad a - mainCRTStartup .def mainCRTStartup .scl 2 .type 32 .endef .globl mainCRTStarup .extern abort mainCRTStartup: sub rsp, 40 movabs rax, offset a movabs rcx, offset mainCRTStartup mov rdx, [c] sub rax, rcx cmp rax, rdx jne 1f xor eax, eax add rsp, 40 ret 1: call abort .section .rdata,"dr" a: .quad 0 The value under "c" is 4092, while the actual difference is 4088. If "a" is moved to .text, or if "c" is a .long instead of a .quad, the problem disappears.
Created attachment 9519 [details] Proper R_X86_64_PC64 reloc handling The patch I propose fixes things for me. Since Microsoft does *not* support R_X86_64_PC64 relocation type for PE-COFF and it is a pure GNU extension, I've decided we can handle it in whatever way we want. The only known to me high-level language compiler which generates this type of relocations on Windows is GHC (Glasgow Haskell Compiler) via LLVM backend (native codegen backend has workaround to generate R_X86_64_PC32 relocations instead). With no above patch applied ld generates wrong executables for it.
The master branch has been updated by Nick Clifton <nickc@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=384f7503344b1d07561f801ced7493858cde6164 commit 384f7503344b1d07561f801ced7493858cde6164 Author: Awson <kyrab@mail.ru> Date: Mon Sep 26 16:16:25 2016 +0100 Fix the calculation of AMD64_PCRQUAD relocations. PR ld/17955 * coff-x86_64.c (coff_amd64_rtype_to_howto): Use an 8 byte offset for R_AMD64_PCRQUAD relocations.
Thanks for the patch. I have applied it with one small change - I made the new code conditional upon DONT_EXTEND_AMD64 not being defined. This is in line with the other uses of R_AMD64_PCRQUAD in the same file.