lli -force-interpreter complains about external function

Hi:

When I try to execute lli -force-interpreter=true hello.bc, it gave the following error:

LLVM ERROR: Tried to execute an unknown external function: i32 (i8*)* puts

I think the error is because C library is not being linked with the byte code, but I was not able to find any helpful instruction in lli’s document.

Can you please teach me how to do it?

Thanks
Xu

The hello.bc is generated as the following:

======file: hello.c======

#include <stdio.h>

int main(int argc, char** argv){
printf(“hello world\n”);
return 0;
}

Xu Yang wrote:

Hi:

When I try to execute lli -force-interpreter=true hello.bc, it gave the
following error:

LLVM ERROR: Tried to execute an unknown external function: i32 (i8*)* puts

I think the error is because C library is not being linked with the byte
code, but I was not able to find any helpful instruction in lli's document.

Can you please teach me how to do it?

The interpreter uses libffi to make external function calls. However, it needs to be detected at LLVM's compile time. If you're using the released packages, we disabled that because we were worried about users who don't have libffi installed.

In short, install libffi and rebuild LLVM.

Nick

Nick Lewycky <nicholas@mxc.ca> writes:

The interpreter uses libffi to make external function calls. However, it
needs to be detected at LLVM's compile time. If you're using the
released packages, we disabled that because we were worried about users
who don't have libffi installed.

This seems to be quite a common problem (I too hit it once, thought it
was a bug and reported it at
5466 – lli -force-interpreter unable to resolve external symbols?) how about making lli inform
the user that LLVM was built without FFI support?

Timo Juhani Lindfors wrote:

Nick Lewycky<nicholas@mxc.ca> writes:

The interpreter uses libffi to make external function calls. However, it
needs to be detected at LLVM's compile time. If you're using the
released packages, we disabled that because we were worried about users
who don't have libffi installed.

This seems to be quite a common problem (I too hit it once, thought it
was a bug and reported it at
5466 – lli -force-interpreter unable to resolve external symbols?) how about making lli inform
the user that LLVM was built without FFI support?

Thanks for the reminder. I recall looking at the patch but I didn't apply it at the time because I couldn't figure out why the code above it used errs() in one case and llvm_report_error in another.

Nick

Hi Nick:

Thanks for pointing me to libffi.
Recompile LLVM with libffi does solve the problem of printf.
But it still has other problems:

  1. sinf() returns 0 in the interpreter, but returns correct value in JIT (see hellosin.c)
  2. calling pthread_create cause lli to crash in the interpreter mode, but no problem in JIT (see phello.c).

My questions are:
i) can I call any arbitrary external function in the interpreter?
ii) how do I specify the dynamic library (where the external function is implemented), when I call the interpreter?

Thanks
Xu

hellosin.c

Hi Nick:

The first problem have been solved by calling llvm-ld:

$ llvm-ld -o hellosin.llvm hellosin.bc -lm
$ lli -force-interpreter=true -load=/usr/lib/libm.so hellosin.llvm.bc
hello sin: 0.50

The pthread problem remains after llvm-ld:

$ lli -force-interpreter=true -load=/lib/libpthread.so.0 phello.llvm.bc
0 lli 0x08796bf8
Segmentation fault

For those who are getting “invalid ELF header” error when calling llvm-ld with -lpthread,
please change the load module from /usr/lib/pthread.a to /lib/libpthread.so.0.

Thanks
Xu

Xu Yang wrote:

Hi Nick:

The first problem have been solved by calling llvm-ld:

$ llvm-ld -o hellosin.llvm hellosin.bc -lm
$ lli -force-interpreter=true -load=/usr/lib/libm.so hellosin.llvm.bc
hello sin: 0.50

Only because the optimizer saw sin(constant) and folded it away. The entire program became 'print constant string'. There is certainly a bug calling sinf() from the interpreter but I don't know what it is yet.

The pthread problem remains after llvm-ld:

$ lli -force-interpreter=true -load=/lib/libpthread.so.0 phello.llvm.bc
0 lli 0x08796bf8
Segmentation fault

I don't expect this to work at all. Unlike the JIT, I don't know of any work having been done to make the interpreter thread-safe.

By the way, the interpreter can't support many more things, such as qsort() or any method which expects to call a function pointer. Is there a reason you need to use the interpreter? It's been largely undermaintained because it's pretty much useless when you've got a working JIT.

Nick

Nick Lewycky wrote:

Xu Yang wrote:

Hi Nick:

The first problem have been solved by calling llvm-ld:

$ llvm-ld -o hellosin.llvm hellosin.bc -lm
$ lli -force-interpreter=true -load=/usr/lib/libm.so hellosin.llvm.bc
hello sin: 0.50

Only because the optimizer saw sin(constant) and folded it away. The
entire program became 'print constant string'. There is certainly a bug
calling sinf() from the interpreter but I don't know what it is yet.

Fixed in r89198.

Nick

Hi Nick:

Thanks for the response.

You are right about sinf.
I changed the constant to sscanf(argv[1], …), and it gave me back 0 again.
I also compared the disassembled code, and saw it was indeed the case.

The primary reason I use interpreter is because I wish to do runtime checking on memory access pattern in multithreaded C programs. for example, if thread one is in the critical section, I wish to know if there are any other threads accessing the variables in the critical section without first acquiring a lock. I can do it with native code, but I will have to insert memory check function calls before all memory access instructions (load/store…), which is painful. But if I can run the program in interpreter, I can intercept the load and store instruction in the interpreter, and do the memory check there, which is completely transparent to the user program.

Do you have any suggestions on how LLVM may help in this case?

Thanks
Xu

Have you looked at
Google Code Archive - Long-term storage for Google Code Project Hosting. or
Valgrind? They have the
advantage of having already been debugged.

Nick Lewycky <nicholas@mxc.ca> writes:

Thanks for the reminder. I recall looking at the patch but I didn't
apply it at the time because I couldn't figure out why the code above
it used errs() in one case and llvm_report_error in another.

What was the reason? (I think I too wondered that.)

Timo Juhani Lindfors wrote:

Nick Lewycky<nicholas@mxc.ca> writes:

Thanks for the reminder. I recall looking at the patch but I didn't
apply it at the time because I couldn't figure out why the code above
it used errs() in one case and llvm_report_error in another.

What was the reason? (I think I too wondered that.)

I have no idea. :slight_smile: I decided that it didn't matter to your patch.

Nick