Relocation issue with jump tables in ELF object files on X86_64

(llvm 2.6)

We have an application where we are using LLVM to generate ELF object files for X86_64. At runtime we load these objects files into memory using our own ELF loader.

Everything is working except for the jump tables.

The ELF emitter is generating JMPQ instructions using X86::reloc_absolute_word_sext relocations which we are unable to patch to the jump table in the .rodata segment unless we force that segment to load in the low 2GB of the address range. Currently we just request pages of memory from the OS and that memory is much deeper in the address space.

Is there proper way to patch the address or instruction (ewww) or have the ELF emitter generate a RIP based instruction. If a real linker doesn’t patch the instruction, does the ELF loader always try to load .rodata segments in the low 2GB of memory regardless of if it is from the main image or from a shared library?

Thanks for any help.

Perhaps you're missing a call to TargetMachine::setRelocationModel?
It sounds like you need PIC codegen.

-Eli

I had this problem a while back and received this response from Jeffrey. FWIW this is fixed in 2.7 by defaulting to CodeModel::Large and using indirect (far) calls.

We generating object files, not using the JIT so I don't know if those fixes applies in our case.

As far as using PIC goes, the ELFCodeEmitter has asserts to tell you that PIC isn't currently supported.

Will have to get the 2.7 update and try it out.

Thanks.

We generating object files, not using the JIT so I don't know if those fixes applies in our case.

As far as using PIC goes, the ELFCodeEmitter has asserts to tell you that PIC isn't currently supported.

Right... the 2.6 ELFCodeEmitter is experimental code which was never
complete enough to handle options like PIC.

Will have to get the 2.7 update and try it out.

ELFCodeEmitter is gone in 2.7; hopefully, similar functionality will
be back in 2.8 without the limitations it had in 2.6. In the
meantime, I'd suggest simply using GNU as.

-Eli