llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.24k stars 12.07k forks source link

RuntimeDyldELF doesn't handle >2GB relocations on x86-64 platforms #15728

Open andykaylor opened 11 years ago

andykaylor commented 11 years ago
Bugzilla Link 15356
Version trunk
OS All
CC @Bigcheese

Extended Description

On x86-64 platforms, RuntimeDyldELF cannot be guaranteed to handle 32-bit relative relocations correctly. Although the SectionMemoryManager attempts to allocate all loaded sections in proximity to one another, this cannot be guaranteed. Furthermore, RuntimeDyldELF should not be dependent upon the memory manager's allocation scheme to perform correctly.

The specific relocation in question is R_X86_64_PC32, which is typically used with a call or jump instruction. It may be possible to solve this problem by generating a stub within the source section that can bridge the gap to the target section. However, some investigation is necessary to verify that this approach will work in all cases.

Note that the assertion in the RuntimeDyldELF handler for the R_X86_64_32 and R_X86_64_32S relocation types covers a different situation. If that assertion fires, it is almost certainly because code was generated with the small memory model and is being loaded above the 2GB boundary. When the small memory model is used on x86-64 (not recommended), it is the responsible of the client code to provide a memory manager which guarantees that code will be loaded below the 2GB boundary.

lhames commented 2 years ago

mentioned in issue llvm/llvm-bugzilla-archive#20457

llvmbot commented 10 years ago

I filed a separate bug as http://llvm.org/bugs/show_bug.cgi?id=21423

llvmbot commented 10 years ago

I believe you should be able to work around that problem by compiling with large memory model, which prevents generation of the relocation in question.

This doesn't seem to be the case.

$ cat test.s test: .cfi_startproc .cfi_endproc $ as test.s -o test.o; readelf -r test.o R_X86_64_PC32 $ llvm-mc -filetype=obj test.s -o test.o; readelf -r test.o R_X86_64_PC32 $ llvm-mc -filetype=obj -code-model=large test.s -o test.o; readelf -r test.o R_X86_64_PC32

That is, this particular relocation is always R_X86_64_PC32, regardless of code model.

andykaylor commented 10 years ago

Which large memory model compiling option are you talking about?

Sorry, llvm calls it CodeModel. I believe it is an argument to most of the API functions for creating an instance of MCJIT, but I believe it can also be embedded in a Module. I'm not sure which one is used if they conflict, but probably the one in the Module.

If you use CodeModel::JITDefault that will get translated to CodeModel::Large on 64-bit x86 platforms. By contrast, CodeModel::Default is translated to CodeModel::Small.

You could also try using the PIC relocation model. I know PIC support is at least partially implemented for Intel64 architecture, but I don't know how robust it is.

llvmbot commented 10 years ago

What is the right solution here?

I believe you should be able to work around that problem by compiling with large memory model, which prevents generation of the relocation in question.

Which large memory model compiling option are you talking about?

andykaylor commented 10 years ago

What is the right solution here?

I believe you should be able to work around that problem by compiling with large memory model, which prevents generation of the relocation in question.

llvmbot commented 10 years ago

FTL http://trac.webkit.org/wiki/FTLJIT seems to hit this problem. FTL tells LLVM to use its own memory manager, instead of using the default SectionMemoryManager.

JavaScriptCore's memory manager happens to allocate code sections and data sections far away, not near to each other. There are R_X86_64_PC32 relocations from .eh_frame (a data section) to .text (a code section), which trigger an assertion failure.

What is the right solution here?

  1. RuntimeDyldELF should handle this case. (How?)
  2. Custom memory managers should allocate sections near to each other.
  3. .eh_frame references to .text should not use R_X86_64_PC32 relocations.
Bigcheese commented 11 years ago

Generating a stub for function calls will work for everything except for function pointer comparison. However there's nothing you can do about data references. I think the proper solution would be to use the Small position independent code model (PIC) and use the GOT/PLT for references, as they can be resolved as 64 bit and will give proper function pointers. I don't see a need to generate large or medium model code.