symbol resolution on statically-compiled JIT


I am using LLVM to create a JIT – I have followed the excellent Kaleidoscope tutorial, and am now starting to build off of it.

Down the line, I plan to use this JIT for my research into computer architecture, which means that I will need to run the JIT itself within a simulated CPU and bare-bones linux system. To make that research easier, I am trying to statically compile my JIT. Everything works with the normal compilation (clang … -rdynamic) but when switched to static (clang … -static), I can no longer execute externally defined C functions. I suspect this is something to do with the symbol loader not being properly set up for static linking, but I don’t know much about that.

Here are some more details:

In the normally-compiled kaleidoscope JIT, I can run something like this:

extern printd(x);

printd was one of the C functions defined within the main program:

/// printd - printf that takes a double prints it as “%f\n”, returning 0.
extern “C” DLLEXPORT double printd(double X) {
fprintf(stderr, “%f\n”, X);
return X;

However, in the static linked version, the JIT cannot find the symbol:

extern printd(x);
kaleidoscope error: Symbols not found: { printd }

But the symbol is there:

$ llvm-nm kld_s | grep printd
0000000000497e30 T printd
$ llvm-nm kld | grep printd

00000000006b1820 T printd

(kld_s is the static version)

How can I begin to debug this issue? Does something different happen to the symbol loader when I compile statically?

My two make scripts look like

$ make kld
clang++ -v kld.cpp libkld.o /home/eli/sproj-git/passes/test/libTestPass.o llvm-config --cxxflags --ldflags --system-libs --libs core orcjit native -fuse-ld=gold -g3 -o kld -rdynamic

$ make kld_s
clang++ -v kld.cpp libkld.o /home/eli/sproj-git/passes/test/libTestPass.o llvm-config --cxxflags --ldflags --system-libs --libs core orcjit native -fuse-ld=gold -g3 -o kld_s -static

The only difference is in the final flag (bold). libkld.o and libTestPass.o are unrelated object files I am linking from other parts of my project.

If the clang option -static behaves like gcc’s, the man page does say that it “… prevents linking with the shared libraries”, which I suppose is not precisely what I want.

I previously emailed llvm-dev a few months ago about a similar issue, where extern functions were not working at all (even dynamically). I resolved that issue by downgrading to LLVM 6, and recently, by upgrading to LLVM 9. Now the issue has returned, I suppose, in slightly different form.

If anyone has any ideas, please let me know!

Thank you so much,
Eli Baum

Hi Eli,

You will need to add the process symbols explicitly to the search space using:


If you are on linux, you will also need to make sure that process symbols are exported by passing -Wl,–export-dynamic to clang, and ensure that any symbols that you want to call are not dead-stripped by the linker.

Hope that helps!