the following snippet of code: void foo(int a,...) { } produces relocation entries as: Relocation section '.rela.text' at offset 0x4f8 contains 1 entries: Offset Info Type Sym. Value Sym. Name + Addend 00000000004b 00020000000b R_X86_64_32S 0000000000000000 .text + 83 Relocation section '.rela.eh_frame' at offset 0x510 contains 1 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000000020 000200000001 R_X86_64_64 0000000000000000 .text + 0 which defeats the purpose of using -mcmodel=medium. the intent here is to link an executable at text=0x80000000, and the signed 32 bit relocation causes the linker to puke. -mcmodel=medium does express all other relocations as R_X86_64_64 (except .debug)
the following assembly (which is trimmed down from the mmx spill code inserted into the routine using varargs) fed into the x86_64 assembler results in the unwanted relocation: movq $.L2, -192(%rbp) .L2: so this seems a gas/binutils issue
-mcmodel changes the way that all references requiring relocation are coded, causing the assembler to produce the correct code. 'medium' mode introduces an intermediate 64 bit register to store the address the presence of varargs in a function on 64 bit causes a spill of the mmx registers, conditional on another register being nonzero (as defined in the x86_64 abi) this spill is handled by ix86_setup_incoming_varags in gcc/config/i386/i386.c this calls a pseudo-instruction, see_prologue_save_insn in gcc/config/i386/i386.md the generation of the computed target at the end of the jump doesn't follow the game generation rule as normal references, and forces the compiler to issue the signed 32 bit reference, which screws up our link
-mcmodel=medium is not supposed to allow linking of code into upper addresses. As defined in the psABI document, it allows only data segment to contain references in upper places. For linking on such addresses use either -mcmodel=kernel or -fPIC