Question

I was trying to get the Microsoft compiler to generate a relocation of type IMAGE_REL_AMD64_ADDR64 for testing purposes. The compiler prefers to use relative 32-bit LEA instructions, which is understandable, but I thought the following program would require it to use a 64-bit relocation:

#include <stdio.h>

char a[5000000000];
char b[5000000000];

int main(){
    printf("%p %p %p %p\n", a, b, b - a, a - b);
}

It didn't, so I tried it with MinGW (both compilers in 64-bit mode on 64-bit Windows), and got the same results, respectively:

0000000169CE5A40 000000013FC86840 FFFFFFFFD5FA0E00 000000002A05F200
000000002A46D580 000000000040E380 FFFFFFFFD5FA0E00 000000002A05F200

I then tried it with GCC on Linux and the result was more enlightening, being a linker error message: 'relocation truncated to fit: R_X86_64_32'.

So just to make sure I'm not missing something, this is a bug in both compilers, except that in the case of GCC on Linux, at least the linker notices the problem instead of silently giving a wrong answer?

And how do you get the Microsoft compiler to generate 64-bit relocations? They occur in the Microsoft standard library (which is what prompted me to try to generate some in the first place) so presumably there must be a way?

Was it helpful?

Solution

Mind you, the bug is understandable because the compiler doesn't know that the offsets will end up exceeding 32 bits; basically it's an interaction between the separate compiling and linking model and a quirk of the x64 instruction set.

Anyway, it turns out you can get actual 64-bit relocations with e.g.

char *p = a;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top