[llvm-dev] Undefined symbols with inline functions using the ORC JIT on Linux

Martin Andersson via llvm-dev
2019-01-05T11:44:38Z

Hi Stefan,

Thanks for your reply. I tried running my simple example on Linux using lli
and it does work fine. So I think the best long-term solution is to migrate
my code to the new lazy orc jit. Unfortunately, even the simplest example
does not work on Windows:
int main() { return 0; }

This is the output:
JITDylib " " (ES: 0x000001b6e4ad3670):
Search order: [ (" ", all) ]
Symbol table:
    "__cxa_atexit": <not resolved> ( Lazy (MU=0x1b6e4ae3110),
[Data] )
    "main": <not resolved> ( Lazy (MU=0x1b6e4ae7f10), [Callable]
)
    "__dso_handle": <not resolved> ( Lazy (MU=0x1b6e4ae3110),
[Data] )

I run with these arguments, and I checked and -fno-use-cxa-atexit is set by
clang:
clang -S -emit-llvm main.cpp
lli -jit-kind=orc-lazy main.ll

Using mcjit and orc-mcjit as the jit-kind in lli works fine on Windows.

I will keep investigating how to best proceed, thanks for pointing me in
the right direction.

//Martin

On Fri, Jan 4, 2019 at 10:49 PM Stefan Gränitz <stefan.graenitz at
gmail.com>
wrote:

> Hi Martin
>
> However, the inline functions are not in that set so they are not promoted
> to strong definitions. Shouldn't functions defined in the jitted code
be
> our responsibility?
> [...]
> This program does not work, clang-interpreter crashes because it cannot
> find the symbol for the Test constructor function.
>
> class Test {
>     public: Test() {}
> };
>
> int main()
> {
>     Test test;
>     return 0;
> }
>
> You could compile your example to bitcode and run it with lli. This will
> provide more information and the issue may be discussed easier on bitcode
> level. (Not very familiar with clang-interpreter, but it looks more like an
> example for illustration than a bulletproof tool.)
>
> Looking closer what happens with the ResponsibiltySet. When it is created
> it tries to to find symbols for all the names it knows about. Eventually
> the look up request ends up in my application [...]
>
> Instead of using the legacy resolvers you might prefer a fallback symbol
> generator here. The lli tool uses this approach to provide symbols from the
> host process for the JITed code (see:
>
https://github.com/llvm-mirror/llvm/blob/8ffa038b3ef4448af8bf31f6c50281779939c774/tools/lli/lli.cpp#L807
> ).
>
> Hope it helps
> Stefan
>
> Am 04.01.19 um 18:49 schrieb Martin Andersson via llvm-dev:
>
> Hi,
>
> I am developing an application that uses the ORC api to JIT compile C++
> code using Clang. So far I have done most of the work on Windows, where it
> now mostly works as expected. However, when I tried to run my application
> on Linux I ran into some problems.
>
> The problem I ran into is that symbols for jitted inline functions cannot
> be resolved. Both LLVM and Clang are checked out with latest master branch.
>
> It is probably me that is doing something wrong but I cannot figure out
> what it is. Here is what I found so far. In the file RuntimeDyld.cpp in
> function loadObjectImpl, a check is made whether a particular function is
> weak or not. Since inline functions are weak (as I understood it) an
> attempt is made to promote this symbol to a strong definition. But only if
> it is present in the "ResponsibilitySet", that check is made on
line 273.
> However, the inline functions are not in that set so they are not promoted
> to strong definitions. Shouldn't functions defined in the jitted code
be
> our responsibility?
>
> Looking closer what happens with the ResponsibiltySet. When it is created
> it tries to to find symbols for all the names it knows about. Eventually
> the look up request ends up in my application where I use a
> LegacyIRCompileLayer to search for the symbol in the jitted module. That
> function call eventually ends up in getSymbol in RTDyldObjectLinkingLayer.h
> where the symbol is found but it does not have and address (Address is zero
> and Flags is 50). So an instance of JITSymbol is returned to the
> LegacyRTDyldObjectLinkingLayer and the findSymbol function which checks if
> an valid symbol was found (on line 406 in RTDyldObjectLinkingLayer.h).
> Since the address is zero the JITSymbol is deemed to be not valid, via the
> bool operator in JITSymbol.h and that is why that particular symbol name
> does not end up in the ResponsibilitySet. That is as far as I got, I
don't
> know enough about LLVM to understand what the problem is (if any).
>
> This issue can be replicated with the clang-interpreter application.
>
> This program does not work, clang-interpreter crashes because it cannot
> find the symbol for the Test constructor function.
>
> class Test {
>     public: Test() {}
> };
>
> int main()
> {
>     Test test;
>     return 0;
> }
>
> This program works:
>
> class Test {
>     public: Test();
> };
>
> Test::Test() { }
>
> int main()
> {
>     Test test;
>     return 0;
> }
>
> The first version works on Windows since the inline constructor is not
> marked as weak. Can anyone enlighten me on what is happening here? Is this
> the expected behavior, and if it is, what am I doing wrong?
>
> Btw, I also tried various compiler flags (fno-inline and
> fno-inline-functions) but those do not help in this case.
>
> //Martin
>
>
> _______________________________________________
> LLVM Developers mailing listllvm-dev at
lists.llvm.orghttp://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20190105/5ed65281/attachment.html>