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:
c: .quad a - mainCRTStartup
sub rsp, 40
movabs rax, offset a
movabs rcx, offset mainCRTStartup
mov rdx, [c]
sub rax, rcx
cmp rax, rdx
xor eax, eax
add rsp, 40
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 <firstname.lastname@example.org>:
Author: Awson <email@example.com>
Date: Mon Sep 26 16:16:25 2016 +0100
Fix the calculation of AMD64_PCRQUAD relocations.
* 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.