llvm / llvm-project

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

How to use `LLJIT::addObjectFile` with extra libraries? #59

Closed lanistor closed 4 years ago

lanistor commented 4 years ago

When i try to link c++ function, error occured:

JIT session error: Symbols not found: { ___cxa_begin_catch, __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5flushEv, __Unwind_Resume, ___cxa_end_catch, __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentryD1Ev, __ZNSt3__18ios_base5clearEj, __ZNSt3__15ctypeIcE2idE, __ZNKSt3__16locale9use_facetERNS0_2idE, __ZSt9terminatev, __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED1Ev, __ZNSt3__14coutE, _memset, __ZNSt3__16localeD1Ev, _strlen, __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEmc, ___gxx_personality_v0, __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentryC1ERS3_, __ZNSt3__18ios_base33__set_badbit_and_consider_rethrowEv, ___cxa_call_unexpected, __ZNKSt3__18ios_base6getlocEv, __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE3putEc }
Failed to materialize symbols: { (0x7fdb6440b810, { __ZNSt3__1lsINS_11char_traitsIcEEEERNS_13basic_ostreamIcT_EES6_PKc, __ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m, _link, __ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_, ___clang_call_terminate, _add, __ZNSt3__111char_traitsIcE3eofEv, __ZNSt3__111char_traitsIcE11eq_int_typeEii, _main, __ZNSt3__111char_traitsIcE6lengthEPKc }) }

Here are my code: main.cpp

InitLLVM X(argc, argv);
  InitializeNativeTarget();
  InitializeNativeTargetAsmPrinter();
  ThreadSafeContext context(std::make_unique<LLVMContext>());

  ExitOnError ExitOnErr;

  jitlink::InProcessMemoryManager MemMgr;

  auto JTMB = ExitOnErr(JITTargetMachineBuilder::detectHost());
  JTMB.setCodeModel(CodeModel::Small);

  auto jit =
      ExitOnErr(LLJITBuilder()
                    .setJITTargetMachineBuilder(std::move(JTMB))
                    .setObjectLinkingLayerCreator([&](ExecutionSession &ES, const Triple &TT) {
                      return std::make_unique<ObjectLinkingLayer>(ES, MemMgr);
                    })
                    .create());
  auto ffi = ExitOnErr(errorOrToExpected(MemoryBuffer::getFileAsStream("build/ffi.o")));
  jit->addObjectFile(std::move(ffi));

  char func_name[] = "add";
  auto add              = ExitOnErr(jit->lookup(func_name));
  int (*func)(int, int) = (int (*)(int, int))add.getAddress();
  int result            = func(111, 222);

ffi.cpp

#include <iostream>

extern "C" int add(int a, int b) {
  std::cout << "add function run" << std::endl;
  return a + b;
}
int main() {
  return add(1, 2);
}

ffi.o was build by clang++ -std=c++17 -stdlib=libc++ ffi.cpp -c -o build/ffi.o; If using clang++ -std=c++17 -stdlib=libc++ ffi.cpp -o build/ffi.o;, another error will occour:

JIT session error: Unsupported file format

JIT session error: Failed to materialize symbols: { (0x7fc530a05580, { _add, __ZNSt3__111char_traitsIcE11eq_int_typeEii, __mh_execute_header, __ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m, __ZNSt3__111char_traitsIcE6lengthEPKc, _main, __ZNSt3__111char_traitsIcE3eofEv, __ZNSt3__1lsINS_11char_traitsIcEEEERNS_13basic_ostreamIcT_EES6_PKc }) }
Failed to materialize symbols: { (0x7fc530a05580, { _link }) }

Relative question: issues/57

lhames commented 4 years ago

JIT session error: Symbols not found: { ___cxa_begin_catch, ... Failed to materialize symbols: { (0x7fdb6440b810, {__ZNSt3__1lsINS_11char_traitsIcEEEERNS_13basic_ostreamIcT_EES6_PKc,...

You seem to have guessed the issue, but to confirm: LLVM's JIT acts as a linker, and you are seeing missing symbols errors because you don't have definitions of some of the symbols that your relocatable object is using. You need to load definitions of those functions into the JIT, or link them into the JIT executable and then make the JIT executable's symbols visible to JIT'd code. See: https://llvm.org/docs/ORCv2.html#how-to-add-process-and-library-symbols-to-the-jitdylibs

In your case a glance at the missing symbols suggest that you will at least need to build your JIT with RTTI and exceptions turned on. I'm not sure whether you will have to do anything special to pull in the iostreams definitions.

clang++ -std=c++17 -stdlib=libc++ ffi.cpp -o build/ffi.o

As I mentioned in https://github.com/llvm/llvm-project/issues/57 you need to use -c -o to produce a relocatable object. Using just -o will result in an executable which definitely will not work.

lanistor commented 4 years ago

@lhames Yeah, it works. Thank you so much.