Different behaviour of multiple ELF relocations on i386 and x86-64

47 Views Asked by At

Per the System V gABI,

If multiple consecutive relocation records are applied to the same relocation location (r_offset), they are composed instead of being applied independently, as described above. By consecutive, we mean that the relocation records are contiguous within a single relocation section. By composed, we mean that [... i]n all but the first relocation operation of a composed sequence, the addend used is the retained result of the previous relocation operation, rather than that implied by the relocation type.

And indeed, if we compile and link the following assembly file

#ifdef __x86_64__
#define R(N) R_X86_64_##N
#else
#define R(N) R_386_##N
#endif

     .globl foo
foo: .int 0
     .reloc foo, R(32), bar
     .reloc foo, R(32), baz

and the following C file

#include <stdio.h>

__asm__(
    ".globl bar\n\t"
    "bar = 0x42\n\t"
    ".globl baz\n\t"
    "baz = 0x57"
);

extern unsigned foo;
int main(void) {
    printf("%X\n", foo);
    return 0;
}

with a 32-bit x86 GCC targeting Linux, the resulting program outputs 99, so both relocations have indeed been applied. However, with a x86-64 GCC, it outputs 57, that is, only the last relocation has had any effect.

I cannot find anything in the AMD64 psABI that would suggest this behaviour; however, it seems to be consistent over GCC and Clang with -fuse-ld=bfd, gold, and lld.

What’s going on?

0

There are 0 best solutions below