Migration from JIT to MCJIT

Hi,

I’m migrating my code (running on mac) from using JIT to MCJIT. My code generates in memory, mostly using the llvm-c api, and then runs the generated code.
When I try to use MCJIT I encounter a problem with relocations of external symbols – functions compiled statically beforehand with gcc.

I get the following error:

Invalid relocation type!
UNREACHABLE executed at /Users/weisse4/dev/llvm/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp:89

While debugging, I see that the relocation type read in RuntimeDyldImpl::loadObject is 218103811, which seems corrupt to me.
Did someone encounter a similar error? Or can direct me to changes that I need to do while migrating from JIT to MCJIT?

Thanks.

Hi Weiss, I do not have any experience on Mach binary format, but the hex value of 218103811 is 0xd000003 (maybe the relocation type is RIT_Generic_PreboundLazyPointer = 3), something looks like a relocation entry composed of “symbol index” + “relocation type”. maybe something is wrong, that the relocation entry is not anded with a mask to get the final relocation type. — Regards, Jiong

Thank you for the help.

The relocation type value is anded with 0xffffffffL. (RuntimeDyldMachO.cpp:214)
Maybe this mask should be different?
Anyway, it seems like this relocation isn’t implemented. (RuntimeDyldMachO.cpp:104)

The MachO handling isn’t always straightforward in that it has a lot of bit fields to handle while it’s also trying to accommodate the format abstractions baked into the interfaces. The actual relocation type gets extracted in the RuntimeDyldMachO::resolveRelocation function (RuntimeDyldMachO.cpp:32) before it is passed on to the architecture-specific handlers. So the mask you mentioned is probably OK.

The fact that this relocation type isn’t handled is, of course, the root of your problem.

MCJIT has grown on an as-needed basis up to now, with only the relocation types we were actually seeing being implemented. Unfortunately, I don’t know enough about MachO to help with this one. Maybe Jim Grosbach can help?

-Andy

Existing clients (LLDB) deal with externals by resolving them to constant function pointers that are referenced in the IR. That’s obviously ugly as hell, but it gets things done.

The old JIT was able to simplify things because it assumed the JITed code was running in the same process as the JIT compiler. The MCJIT doesn’t assume that, so it has to handle more possibilities. For example, that the invoked function may be in a dylib which hasn’t yet been loaded into the target address space. I suggest having a look at the ld64, lld and dyld implementations to see what these relocation really imply. You won’t have to solve all of the potential scenarios to get anything done, but you will want to make sure to carefully check which use-case you’re in and error out when it’s one you haven’t handled yet. The worst case is if the code makes overly broad assumptions about possible inputs and resolves a relocation incorrectly in some subtle way.

-Jim

Eran,

Is there any chance you could boil this down to a small reproducer?

I’ve got a mid-to-long-term goal of getting rid of the ugliness in LLDB that Jim mentioned, and fixing your problem would be a good first step.

Thanks,

Andy

Eran,

Is there any chance you could boil this down to a small reproducer?

I’ve got a mid-to-long-term goal of getting rid of the ugliness in LLDB that Jim mentioned, and fixing your problem would be a good first step.

Thanks,

Andy

mcjit_external_symbol.cpp (2.62 KB)

Thanks, Eran.

I’m not sure how soon I’ll have a solution for you, but it’s on my to-do list now. I’ll also create a bugzilla record for this problem.

-Andy

Submitted to bugzilla as PR 15729

I think I fixed this for 64 bits while trying to get exception
handling to work. Eran, can you confirm?

Cheers,
Rafael

I’ve checked this for 32 bits, and it works.

Thank you.

Eran.